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
86 changes: 0 additions & 86 deletions test/api_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const itBehavesLike = helper.itBehavesLike;
const TEST_TAG = helper.TEST_TAG;
const UPLOAD_TAGS = helper.UPLOAD_TAGS;
const uploadImage = helper.uploadImage;
const TEST_ID = Date.now();
const SUFFIX = helper.SUFFIX;
const PUBLIC_ID_PREFIX = "npm_api_test";
const PUBLIC_ID = PUBLIC_ID_PREFIX + SUFFIX;
Expand Down Expand Up @@ -44,12 +43,6 @@ const EXPLICIT_TRANSFORMATION2 = {
crop: "scale",
overlay: `text:Arial_60:${TEST_TAG}`,
};
const METADATA_EXTERNAL_ID_UPLOAD = "metadata_upload_" + TEST_ID;
const METADATA_EXTERNAL_ID_UPDATE = "metadata_uploader_update_" + TEST_ID;
const METADATA_EXTERNAL_ID_EXPLICIT = "metadata_explicit_" + TEST_ID;
const LABEL_INT_1 = 'metadata_label_1_' + TEST_ID;
const LABEL_INT_2 = 'metadata_label_2_' + TEST_ID;
const LABEL_INT_3 = 'metadata_label_3_' + TEST_ID;

function wait(ms = 0) {
return new Promise((resolve) => {
Expand Down Expand Up @@ -828,85 +821,6 @@ describe("api", function () {
});
});
});
describe("structured metadata fields", function () {
this.timeout(helper.TIMEOUT_LONG);
const METADATA_VALUE = "123456";
before(function () {
return Q.allSettled(
[
cloudinary.v2.api.add_metadata_field({
external_id: METADATA_EXTERNAL_ID_UPDATE,
label: LABEL_INT_1,
type: "string",
}),
cloudinary.v2.api.add_metadata_field({
external_id: METADATA_EXTERNAL_ID_UPLOAD,
label: LABEL_INT_2,
type: "string",
}),
cloudinary.v2.api.add_metadata_field({
external_id: METADATA_EXTERNAL_ID_EXPLICIT,
label: LABEL_INT_3,
type: "string",
}),
]
).finally(function () {});
});
after(function () {
return Q.allSettled(
[
cloudinary.v2.api.delete_metadata_field(METADATA_EXTERNAL_ID_UPDATE),
cloudinary.v2.api.delete_metadata_field(METADATA_EXTERNAL_ID_UPLOAD),
cloudinary.v2.api.delete_metadata_field(METADATA_EXTERNAL_ID_EXPLICIT),
]
).finally(function () {});
});
it("should be updatable with uploader.update_metadata", function () {
let publicId;
return uploadImage({
tags: [TEST_TAG],
})
.then((result) => {
publicId = result.public_id;
return cloudinary.v2.uploader.update_metadata({ [METADATA_EXTERNAL_ID_UPDATE]: METADATA_VALUE }, [publicId]);
})
.then((result) => {
expect(result).not.to.be.empty();
expect(result.public_ids[0]).to.eql(publicId);
return cloudinary.v2.api.resource(publicId);
})
.then((result) => {
expect(result.metadata[METADATA_EXTERNAL_ID_UPDATE]).to.eql(METADATA_VALUE);
});
});
it("should be supported when uploading a resource with metadata", function () {
return uploadImage({
tags: [TEST_TAG],
metadata: { [METADATA_EXTERNAL_ID_UPLOAD]: METADATA_VALUE },
}).then((result) => {
expect(result).not.to.be.empty();
return cloudinary.v2.api.resource(result.public_id);
}).then((result) => {
expect(result.metadata[METADATA_EXTERNAL_ID_UPLOAD]).to.eql(METADATA_VALUE);
});
});
it("should be supported when calling explicit with metadata", function () {
return uploadImage({
tags: [TEST_TAG],
}).then((result) => {
return cloudinary.v2.uploader.explicit(result.public_id, {
type: "upload",
tags: [TEST_TAG],
metadata: { [METADATA_EXTERNAL_ID_EXPLICIT]: METADATA_VALUE },
});
}).then(function (result) {
expect(result).not.to.be.empty();
return cloudinary.v2.api.resource(result.public_id);
}).then((result) => {
expect(result.metadata[METADATA_EXTERNAL_ID_EXPLICIT]).to.eql(METADATA_VALUE);
});
});
});
it("should support listing by moderation kind and value", function () {
itBehavesLike("a list with a cursor", cloudinary.v2.api.resources_by_moderation, "manual", "approved");
return helper.mockPromise((xhr, write, request) => ["approved", "pending", "rejected"].forEach((stat) => {
Expand Down
91 changes: 83 additions & 8 deletions test/spechelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,52 @@ expect.Assertion.prototype.beServedByCloudinary = function (done) {
return this;
};

/**
* Asserts that a given object is a datasource.
*
* @returns {expect.Assertion}
*/
expect.Assertion.prototype.beADatasource = function () {
let datasource;
datasource = this.obj;
this.assert('values' in datasource, function () {
return `expected datasource to contain mandatory field: 'values'`;
}, function () {
return `expected datasource not to contain a 'values' field`;
});
if (!isEmpty(datasource.values)) {
datasource.values.forEach((value) => {
this.assert(typeof value.value === 'string', function () {
return `expected datasource to contain item with mandatory field 'value' type string`;
}, function () {
return `expected datasource not to contain item with mandatory field 'value' type string`;
});
this.assert(typeof value.external_id === 'string', function () {
return `expected datasource field to contain item with mandatory field: 'value' type string`;
}, function () {
return `expected datasource not to contain item with mandatory field 'external_id' type string`;
});
if (!isEmpty(value.state)) {
const states = ['active', 'inactive'];
this.assert(includes(states, value.state), function () {
return `expected datasource field state to be one of ${states.join(', ')}. Unknown state ${value.state} received`;
}, function () {
return `expected datasource field state not to be of a certain state`;
});
}
});
}
return this;
};

/**
* Asserts that a given object is a metadata field.
* Optionally tests the values in the metadata field for equality
*
* @param {string} type The type of metadata field we expect
* @returns {expect.Assertion}
*/
expect.Assertion.prototype.beAMetadataField = function () {
expect.Assertion.prototype.beAMetadataField = function (type = '') {
let metadataField, expectedValues;
if (Array.isArray(this.obj)) {
[metadataField, expectedValues] = this.obj;
Expand All @@ -145,16 +184,24 @@ expect.Assertion.prototype.beAMetadataField = function () {
}, function () {
return `expected metadata field of type ${metadataField.type} not to contain a datasource field`;
});
expect(metadataField.datasource).to.beADatasource();
}

// Make sure type is acceptable
const acceptableTypes = ['string', 'integer', 'date', 'enum', 'set'];
this.assert(includes(acceptableTypes, metadataField.type), function () {
return `expected metadata field type to be one of ${acceptableTypes.join(', ')}. Unknown field type ${metadataField.type} received`;
}, function () {
return `expected metadata field not to be of a certain type`;
});

if (type) {
this.assert(type === metadataField.type, function () {
return `expected metadata field type to equal ${type}`;
}, function () {
return `expected metadata field type ${metadataField.type} not to equal ${type}`;
});
} else {
const acceptableTypes = ['string', 'integer', 'date', 'enum', 'set'];
this.assert(includes(acceptableTypes, metadataField.type), function () {
return `expected metadata field type to be one of ${acceptableTypes.join(', ')}. Unknown field type ${metadataField.type} received`;
}, function () {
return `expected metadata field not to be of a certain type`;
});
}
// Verify object values
if (expectedValues) {
Object.entries(expectedValues).forEach(([key, value]) => {
Expand Down Expand Up @@ -233,6 +280,23 @@ exports.apiParamMatcher = function (name, value) {
};
};

/**
Create a matcher method for api JSON parameters
@private
@function helper.apiJsonParamMatcher
@param {string} name the parameter name
@param {*} value the parameter value
@return {function} the matcher function as (arg)->Boolean
*/
exports.apiJsonParamMatcher = function (name, value) {
return function (arg) {
var expected, jsonArg;
jsonArg = JSON.parse(arg);
expected = JSON.stringify(value);
return jsonArg[name] && JSON.stringify(jsonArg[name]) === expected;
};
};

/**
Escape RegExp characters
@private
Expand Down Expand Up @@ -328,3 +392,14 @@ exports.setupCache = function () {
exports.uploadImage = function (options) {
return cloudinary.v2.uploader.upload(exports.IMAGE_FILE, options);
};

/**
* Convert a timestamp to the date part of an ISO8601 string
*
* @param {string} timestamp The timestamp to convert
* @returns {string} The date part of a ISO8601 date time
*/
exports.toISO8601DateOnly = function (timestamp) {
const date = new Date(timestamp);
return date.toISOString().split('T')[0];
};
Loading