From 8f19e16924c9b4e27e9e24f3f92587011bb14833 Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Wed, 13 Sep 2023 17:57:47 +0530 Subject: [PATCH 1/3] feat: :sparkles: Taxonomy Implementation with docs, unit and api test cases --- lib/stack/index.js | 23 +++++++ lib/stack/taxonomy/index.js | 110 ++++++++++++++++++++++++++++++ test/api/taxonomy-test.js | 85 +++++++++++++++++++++++ test/test.js | 1 + test/unit/index.js | 1 + test/unit/mock/objects.js | 22 ++++-- test/unit/taxonomy-test.js | 132 ++++++++++++++++++++++++++++++++++++ 7 files changed, 368 insertions(+), 6 deletions(-) create mode 100644 lib/stack/taxonomy/index.js create mode 100644 test/api/taxonomy-test.js create mode 100644 test/unit/taxonomy-test.js diff --git a/lib/stack/index.js b/lib/stack/index.js index 94cde5fa..a0b13c9e 100644 --- a/lib/stack/index.js +++ b/lib/stack/index.js @@ -18,6 +18,7 @@ import { Label } from './label' import { Branch } from './branch' import { BranchAlias } from './branchAlias' import { AuditLog } from './auditlog' +import { Taxonomy } from './taxonomy' // import { format } from 'util' /** * A stack is a space that stores the content of a project (a web or mobile property). Within a stack, you can create content structures, content entries, users, etc. related to the project. Read more about Stacks. @@ -743,6 +744,28 @@ export function Stack (http, data) { } return new AuditLog(http, data) } + + /** + * @description Taxonomies allow you to group a collection of content within a stack. Using taxonomies you can group content types that need to work together + * @param {String} uid The UID of the Taxonomy you want to get details. + * @returns {Taxonomy} Instance of Taxonomy. + * @example + * import * as contentstack from '@contentstack/management' + * const client = contentstack.client() + * + * client.stack({ api_key: 'api_key'}).taxonomy().create() + * .then((taxonomy) => console.log(taxonomy)) + * + * client.stack({ api_key: 'api_key'}).taxonomy('taxonomy_uid').fetch() + * .then((taxonomy) => console.log(taxonomy)) + */ + this.taxonomy = (taxonomyUid = '') => { + const data = { stackHeaders: this.stackHeaders } + if (taxonomyUid) { + data.taxonomy = { uid: taxonomyUid } + } + return new Taxonomy(http, data) + } } return this } diff --git a/lib/stack/taxonomy/index.js b/lib/stack/taxonomy/index.js new file mode 100644 index 00000000..a4989712 --- /dev/null +++ b/lib/stack/taxonomy/index.js @@ -0,0 +1,110 @@ +import cloneDeep from 'lodash/cloneDeep' +import { + create, + fetch, + query, + update, + deleteEntity +} from '../../entity' + +export function Taxonomy (http, data) { + this.stackHeaders = data.stackHeaders + this.urlPath = `/taxonomies` + + if (data.taxonomy) { + Object.assign(this, cloneDeep(data.taxonomy)) + this.urlPath = `/taxonomies/${this.uid}` + + /** + * @description The Update taxonomy call is used to update an existing taxonomy. + * @memberof Taxonomy + * @func update + * @returns {Promise} Promise for Taxonomy instance + * @example + * import * as contentstack from '@contentstack/management' + * const client = contentstack.client() + * + * client.stack({ api_key: 'api_key'}).taxonomy('taxonomy_uid').fetch() + * .then((taxonomy) => { + * taxonomy.name = 'taxonomy name' + * return taxonomy.update() + * }) + * .then((taxonomy) => console.log(taxonomy)) + * + */ + this.update = update(http, 'taxonomy') + + /** + * @description The Delete taxonomy call is used to delete an existing taxonomy. + * @memberof Taxonomy + * @func delete + * @returns {Promise} Response Object. + * @example + * import * as contentstack from '@contentstack/management' + * const client = contentstack.client() + * + * client.stack({ api_key: 'api_key'}).taxonomy('taxonomy_uid').delete() + * .then((response) => console.log(response.notice)) + * + */ + this.delete = deleteEntity(http) + + /** + * @description The Fetch taxonomy call is used to fetch an existing taxonomy. + * @memberof Taxonomy + * @func fetch + * @returns {Promise} Promise for Taxonomy instance + * @example + * import * as contentstack from '@contentstack/management' + * const client = contentstack.client() + * + * client.stack({ api_key: 'api_key'}).taxonomy('taxonomy_uid').fetch() + * .then((taxonomy) => console.log(taxonomy)) + * + */ + this.fetch = fetch(http, 'taxonomy') + } else { + /** + * @description The Create taxonomy call is used to create a taxonomy. + * @memberof Taxonomy + * @func create + * @returns {Promise} Promise for Taxonomy instance + * @example + * import * as contentstack from '@contentstack/management' + * const client = contentstack.client() + * const taxonomy = { + * uid: 'taxonomy_testing1', + * name: 'taxonomy testing', + * description: 'Description for Taxonomy testing' + * } + * client.stack({ api_key: 'api_key'}).taxonomy().create({taxonomy}) + * .then(taxonomy) => console.log(taxonomy) + * + */ + this.create = create({ http }) + + /** + * @description The Query on Taxonomy will allow to fetch details of all Taxonomies. + * @memberof Taxonomy + * @param {Object} params - URI parameters + * @prop {Object} params.query - Queries that you can use to fetch filtered results. + * @func query + * @returns {Array} Array of Taxonomy. + * + * @example + * import * as contentstack from '@contentstack/management' + * const client = contentstack.client() + * + * client.stack().taxonomy().query().find() + * .then((taxonomies) => console.log(taxonomies) + */ + this.query = query({ http: http, wrapperCollection: TaxonomyCollection }) + } +} +export function TaxonomyCollection (http, data) { + const obj = cloneDeep(data.taxonomy) || [] + const taxonomyCollection = obj.map((userdata) => { + return new Taxonomy(http, { taxonomy: userdata, stackHeaders: data.stackHeaders }) + }) + return taxonomyCollection +} diff --git a/test/api/taxonomy-test.js b/test/api/taxonomy-test.js new file mode 100644 index 00000000..d1c6b147 --- /dev/null +++ b/test/api/taxonomy-test.js @@ -0,0 +1,85 @@ +import { expect } from 'chai' +import { describe, it, setup } from 'mocha' +import { jsonReader } from '../utility/fileOperations/readwrite' +import { contentstackClient } from '../utility/ContentstackClient.js' + +var client = {} +var stack = {} + +const taxonomy = { + uid: 'taxonomy_testing1', + name: 'taxonomy testing', + description: 'Description for Taxonomy testing' +} + +var taxonomyUID = '' +// var taxonomyDelUID = 'taxonomy_testing' + +describe('taxonomy api Test', () => { + setup(() => { + const user = jsonReader('loggedinuser.json') + stack = jsonReader('stack.json') + client = contentstackClient(user.authtoken) + }) + + it('Create taxonomy', done => { + makeTaxonomy() + .create([{ taxonomy }]) + .then((taxonomyResponse) => { + expect(taxonomyResponse.name).to.be.equal(taxonomy.name) + done() + }) + .catch(done) + }) + + it('Fetch taxonomy from uid', done => { + makeTaxonomy(taxonomyUID) + .fetch() + .then((taxonomyResponse) => { + expect(taxonomyResponse.name).to.be.equal(taxonomy.name) + done() + }) + .catch(done) + }) + + it('Update taxonomy from uid', done => { + makeTaxonomy(taxonomyUID) + .fetch() + .then((taxonomyResponse) => { + taxonomyResponse.name = 'Updated Name' + return taxonomyResponse.update() + }) + .then((taxonomyResponse) => { + expect(taxonomyResponse.uid).to.be.equal(taxonomyUID) + expect(taxonomyResponse.name).to.be.equal('Updated Name') + done() + }) + .catch(done) + }) + + // it('Delete taxonomy from uid', done => { + // makeTaxonomy(taxonomyDelUID) + // .delete() + // .then((taxonomyResponse) => { + // expect(taxonomyResponse.notice).to.be.equal('Taxonomy deleted successfully.') + // done() + // }) + // .catch(done) + // }) + + it('Query to get all taxonomies', async () => { + makeTaxonomy() + .query() + .find() + .then((response) => { + response.items.forEach((taxonomyResponse) => { + expect(taxonomyResponse.uid).to.be.not.equal(null) + expect(taxonomyResponse.name).to.be.not.equal(null) + }) + }) + }) +}) + +function makeTaxonomy (uid = null) { + return client.stack({ api_key: stack.api_key }).taxonomy(uid) +} diff --git a/test/test.js b/test/test.js index 818f04cb..30f75299 100644 --- a/test/test.js +++ b/test/test.js @@ -25,3 +25,4 @@ require('./api/release-test') require('./api/label-test') require('./api/contentType-delete-test') require('./api/delete-test') +require('./api/taxonomy-test') diff --git a/test/unit/index.js b/test/unit/index.js index abd607f4..77316e2a 100644 --- a/test/unit/index.js +++ b/test/unit/index.js @@ -33,3 +33,4 @@ require('./deployment-test') require('./app-request-test') require('./authorization-test') require('./auditLog-test') +require('./taxonomy-test') diff --git a/test/unit/mock/objects.js b/test/unit/mock/objects.js index b525b6c6..0948d14f 100644 --- a/test/unit/mock/objects.js +++ b/test/unit/mock/objects.js @@ -539,7 +539,7 @@ const appInstallMock = { status: 'installed', installation_uid: 'installationUID', redirect_to: 'config', - redirect_uri: 'redirect_uri', + redirect_uri: 'redirect_uri' } const installationMock = { @@ -613,7 +613,7 @@ const branchCompareAllMock = { compare_branch: 'dev' }, diff: [...globalFieldDiff, ...contentTypeDiff], - next_url:'https://api.contentstack.io/v3/stacks/branches/compare?base_branch=main&compare_branch=dev&skip=0&limit=100' + next_url: 'https://api.contentstack.io/v3/stacks/branches/compare?base_branch=main&compare_branch=dev&skip=0&limit=100' } const branchCompareContentTypeMock = { @@ -621,8 +621,8 @@ const branchCompareContentTypeMock = { base_branch: 'UID', compare_branch: 'dev' }, - diff: [ ...contentTypeDiff ], - next_url:'https://api.contentstack.io/v3/stacks/branches/compare?base_branch=main&compare_branch=dev&skip=0&limit=100' + diff: [...contentTypeDiff], + next_url: 'https://api.contentstack.io/v3/stacks/branches/compare?base_branch=main&compare_branch=dev&skip=0&limit=100' } const branchCompareGlobalFieldMock = { @@ -631,7 +631,7 @@ const branchCompareGlobalFieldMock = { compare_branch: 'dev' }, diff: [...globalFieldDiff], - next_url:'https://api.contentstack.io/v3/stacks/branches/compare?base_branch=main&compare_branch=dev&skip=0&limit=100' + next_url: 'https://api.contentstack.io/v3/stacks/branches/compare?base_branch=main&compare_branch=dev&skip=0&limit=100' } const branchMergeAllMock = { @@ -647,7 +647,7 @@ const branchMergeAllMock = { status: 'in_progress' }, merged_at: null, - errors: [ + errors: [ { code: 'error_code', message: 'Error message' @@ -725,6 +725,15 @@ const auditLogsMock = { ] } +const taxonomyMock = { + uid: 'UID', + name: 'name', + description: 'Description for Taxonomy', + terms_count: 4, + referenced_terms_count: 3, + referenced_entries_count: 6 +} + function mockCollection (mockData, type) { const mock = { ...cloneDeep(noticeMock), @@ -793,6 +802,7 @@ export { branchMergeQueueFetchMock, auditLogsMock, auditLogItemMock, + taxonomyMock, mockCollection, entryMockCollection, checkSystemFields diff --git a/test/unit/taxonomy-test.js b/test/unit/taxonomy-test.js new file mode 100644 index 00000000..b9435185 --- /dev/null +++ b/test/unit/taxonomy-test.js @@ -0,0 +1,132 @@ +import Axios from 'axios' +import { expect } from 'chai' +import { describe, it } from 'mocha' +import MockAdapter from 'axios-mock-adapter' +import { Taxonomy } from '../../lib/stack/taxonomy' +import { systemUidMock, stackHeadersMock, taxonomyMock, noticeMock } from './mock/objects' + +describe('Contentstack Taxonomy test', () => { + it('taxonomy create test', done => { + var mock = new MockAdapter(Axios) + mock.onPost('/taxonomies').reply(200, { + taxonomy: { + ...taxonomyMock + } + }) + makeTaxonomy() + .create() + .then((taxonomy) => { + checkTaxonomy(taxonomy) + done() + }) + .catch(done) + }) + it('Taxonomy fetch test', done => { + var mock = new MockAdapter(Axios) + mock.onGet('/taxonomies/UID').reply(200, { + taxonomy: { + ...taxonomyMock + } + }) + makeTaxonomy({ + taxonomy: { + ...systemUidMock + }, + stackHeaders: stackHeadersMock + }) + .fetch() + .then((taxonomy) => { + checkTaxonomy(taxonomy) + done() + }) + .catch(done) + }) + it('Taxonomies query test', done => { + var mock = new MockAdapter(Axios) + mock.onGet('/taxonomies').reply(200, { + taxonomy: [ + taxonomyMock + ] + }) + makeTaxonomy() + .query() + .find() + .then((taxonomies) => { + checkTaxonomy(taxonomies.items[0]) + done() + }) + .catch(done) + }) + it('Taxonomy update test', done => { + var mock = new MockAdapter(Axios) + mock.onPut('/taxonomies/UID').reply(200, { + taxonomy: { + ...taxonomyMock + } + }) + makeTaxonomy({ + taxonomy: { + ...systemUidMock + }, + stackHeaders: stackHeadersMock + }) + .update() + .then((taxonomy) => { + checkTaxonomy(taxonomy) + done() + }) + .catch(done) + }) + it('taxonomy delete test', done => { + var mock = new MockAdapter(Axios) + mock.onDelete('/taxonomies/UID').reply(200, { + ...noticeMock + }) + makeTaxonomy({ + taxonomy: { + ...systemUidMock + }, + stackHeaders: stackHeadersMock + }) + .delete() + .then((response) => { + expect(response.notice).to.be.equal(noticeMock.notice) + done() + }) + .catch(done) + }) + it('Taxonomy test without uid', done => { + const taxonomy = makeTaxonomy() + expect(taxonomy.urlPath).to.be.equal('/taxonomies') + expect(taxonomy.stackHeaders).to.be.equal(undefined) + expect(taxonomy.update).to.be.equal(undefined) + expect(taxonomy.delete).to.be.equal(undefined) + expect(taxonomy.fetch).to.be.equal(undefined) + expect(taxonomy.create).to.not.equal(undefined) + expect(taxonomy.query).to.not.equal(undefined) + done() + }) + it('Taxonomy test with uid', done => { + const taxonomy = makeTaxonomy({ + taxonomy: { + ...systemUidMock + } + }) + expect(taxonomy.urlPath).to.be.equal(`/taxonomies/${systemUidMock.uid}`) + expect(taxonomy.stackHeaders).to.be.equal(undefined) + expect(taxonomy.update).to.not.equal(undefined) + expect(taxonomy.delete).to.not.equal(undefined) + expect(taxonomy.fetch).to.not.equal(undefined) + expect(taxonomy.create).to.be.equal(undefined) + expect(taxonomy.query).to.be.equal(undefined) + done() + }) +}) + +function makeTaxonomy (data = {}) { + return new Taxonomy(Axios, data) +} + +function checkTaxonomy (taxonomy) { + expect(taxonomy.name).to.be.equal('name') +} From aff9588a6fdd58b1c45a0c86d8d4e92581983ec3 Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Wed, 13 Sep 2023 19:42:46 +0530 Subject: [PATCH 2/3] test: :white_check_mark: changes made in taxonomy function in stack class --- lib/stack/index.js | 44 +++++++++++++++++++-------------------- test/api/taxonomy-test.js | 3 ++- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/lib/stack/index.js b/lib/stack/index.js index a0b13c9e..9453a74b 100644 --- a/lib/stack/index.js +++ b/lib/stack/index.js @@ -685,6 +685,28 @@ export function Stack (http, data) { } return new Role(http, data) } + + /** + * @description Taxonomies allow you to group a collection of content within a stack. Using taxonomies you can group content types that need to work together + * @param {String} uid The UID of the Taxonomy you want to get details. + * @returns {Taxonomy} Instance of Taxonomy. + * @example + * import * as contentstack from '@contentstack/management' + * const client = contentstack.client() + * + * client.stack({ api_key: 'api_key'}).taxonomy().create() + * .then((taxonomy) => console.log(taxonomy)) + * + * client.stack({ api_key: 'api_key'}).taxonomy('taxonomy_uid').fetch() + * .then((taxonomy) => console.log(taxonomy)) + */ + this.taxonomy = (taxonomyUid = '') => { + const data = { stackHeaders: this.stackHeaders } + if (taxonomyUid) { + data.taxonomy = { uid: taxonomyUid } + } + return new Taxonomy(http, data) + } } else { /** * @description The Create stack call creates a new stack in your Contentstack account. @@ -744,28 +766,6 @@ export function Stack (http, data) { } return new AuditLog(http, data) } - - /** - * @description Taxonomies allow you to group a collection of content within a stack. Using taxonomies you can group content types that need to work together - * @param {String} uid The UID of the Taxonomy you want to get details. - * @returns {Taxonomy} Instance of Taxonomy. - * @example - * import * as contentstack from '@contentstack/management' - * const client = contentstack.client() - * - * client.stack({ api_key: 'api_key'}).taxonomy().create() - * .then((taxonomy) => console.log(taxonomy)) - * - * client.stack({ api_key: 'api_key'}).taxonomy('taxonomy_uid').fetch() - * .then((taxonomy) => console.log(taxonomy)) - */ - this.taxonomy = (taxonomyUid = '') => { - const data = { stackHeaders: this.stackHeaders } - if (taxonomyUid) { - data.taxonomy = { uid: taxonomyUid } - } - return new Taxonomy(http, data) - } } return this } diff --git a/test/api/taxonomy-test.js b/test/api/taxonomy-test.js index d1c6b147..6bf2eb49 100644 --- a/test/api/taxonomy-test.js +++ b/test/api/taxonomy-test.js @@ -36,7 +36,8 @@ describe('taxonomy api Test', () => { makeTaxonomy(taxonomyUID) .fetch() .then((taxonomyResponse) => { - expect(taxonomyResponse.name).to.be.equal(taxonomy.name) + expect(taxonomyResponse.uid).to.be.equal(taxonomyUID) + expect(taxonomyResponse.name).to.be.not.equal(null) done() }) .catch(done) From c6788f2c2ccb261694cf36ef166325ed8683df84 Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Thu, 14 Sep 2023 12:08:16 +0530 Subject: [PATCH 3/3] test: uncommented 'detele' api test case --- lib/stack/index.js | 2 +- test/api/taxonomy-test.js | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/stack/index.js b/lib/stack/index.js index 9453a74b..d86f72cb 100644 --- a/lib/stack/index.js +++ b/lib/stack/index.js @@ -19,7 +19,7 @@ import { Branch } from './branch' import { BranchAlias } from './branchAlias' import { AuditLog } from './auditlog' import { Taxonomy } from './taxonomy' -// import { format } from 'util' + /** * A stack is a space that stores the content of a project (a web or mobile property). Within a stack, you can create content structures, content entries, users, etc. related to the project. Read more about Stacks. * @namespace Stack diff --git a/test/api/taxonomy-test.js b/test/api/taxonomy-test.js index 6bf2eb49..2ecc7c73 100644 --- a/test/api/taxonomy-test.js +++ b/test/api/taxonomy-test.js @@ -13,7 +13,7 @@ const taxonomy = { } var taxonomyUID = '' -// var taxonomyDelUID = 'taxonomy_testing' +var taxonomyDelUID = 'taxonomy_testing' describe('taxonomy api Test', () => { setup(() => { @@ -58,15 +58,15 @@ describe('taxonomy api Test', () => { .catch(done) }) - // it('Delete taxonomy from uid', done => { - // makeTaxonomy(taxonomyDelUID) - // .delete() - // .then((taxonomyResponse) => { - // expect(taxonomyResponse.notice).to.be.equal('Taxonomy deleted successfully.') - // done() - // }) - // .catch(done) - // }) + it('Delete taxonomy from uid', done => { + makeTaxonomy(taxonomyDelUID) + .delete() + .then((taxonomyResponse) => { + expect(taxonomyResponse.notice).to.be.equal('Taxonomy deleted successfully.') + done() + }) + .catch(done) + }) it('Query to get all taxonomies', async () => { makeTaxonomy()