From c77c807e8fbd9fe3460f38ab31cd710069fd1dd8 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Wed, 24 Jan 2024 14:17:34 +0530 Subject: [PATCH] Next (#115) * test: Added locale test suit and delete test suit to sanity folder * chore: updated package-lock file * Added taxonomy import/export support (#112) Co-authored-by: Nadeem <110535104+nadeem-cs@users.noreply.github.com> * Validating the object when update the entries with assets (#114) Co-authored-by: Nadeem <110535104+nadeem-cs@users.noreply.github.com> --------- Co-authored-by: harshithad0703 Co-authored-by: harshithad0703 <104908717+harshithad0703@users.noreply.github.com> Co-authored-by: Nadeem <110535104+nadeem-cs@users.noreply.github.com> --- CHANGELOG.md | 11 ++- README.md | 2 +- lib/entity.js | 2 +- lib/stack/taxonomy/index.js | 82 ++++++++++++++++- package-lock.json | 16 ++++ package.json | 7 +- sanity-report.mjs | 31 ++++--- test/sanity-check/api/create-test.js | 0 test/sanity-check/api/delete-test.js | 68 ++++++++++++++ test/sanity-check/api/locale-test.js | 127 +++++++++++++++++++++++++++ test/sanity-check/sanity.js | 2 + 11 files changed, 329 insertions(+), 19 deletions(-) create mode 100644 test/sanity-check/api/create-test.js create mode 100644 test/sanity-check/api/delete-test.js create mode 100644 test/sanity-check/api/locale-test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 23923286..d28b6df0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,16 @@ # Changelog -## [v1.13.1](https://github.com/contentstack/contentstack-management-javascript/tree/v1.13.1) (2023-12-13) +## [v1.15.0](https://github.com/contentstack/contentstack-management-javascript/tree/v1.15.0) (2024-01-23) + - Feature + - Taxonomy Import/Export feature added +## [v1.14.1](https://github.com/contentstack/contentstack-management-javascript/tree/v1.14.1) (2024-11-23) - Fixes - - Fix for issue while updating entries with assets - + - Fix for validating the data while updating entries with assets ## [v1.14.0](https://github.com/contentstack/contentstack-management-javascript/tree/v1.14.0) (2023-12-19) - Feature - Management token feature added +## [v1.13.1](https://github.com/contentstack/contentstack-management-javascript/tree/v1.13.1) (2023-12-13) + - Fixes + - Fix for issue while updating entries with assets ## [v1.13.0](https://github.com/contentstack/contentstack-management-javascript/tree/v1.13.0) (2023-11-21) - Feature - Teams API support diff --git a/README.md b/README.md index 1296e588..432838fb 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ contentstackClient.stack({ api_key: 'API_KEY' }).asset().create({ asset }) - [Content Management API Docs](https://www.contentstack.com/docs/developers/apis/content-management-api) ### The MIT License (MIT) -Copyright © 2012-2023 [Contentstack](https://www.contentstack.com/). All Rights Reserved +Copyright © 2012-2024 [Contentstack](https://www.contentstack.com/). All Rights Reserved Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/lib/entity.js b/lib/entity.js index 268d930d..c81776ba 100644 --- a/lib/entity.js +++ b/lib/entity.js @@ -317,7 +317,7 @@ function isAsset (data) { } export function cleanAssets (data) { - if (typeof data === "object" && Object.keys(data).length > 0) { + if (data && typeof data === "object" && Object.keys(data).length > 0) { const keys = Object.keys(data); for (const key of keys) { if (typeof data[key] === "object" && Object.keys(data[key]).length > 0) { diff --git a/lib/stack/taxonomy/index.js b/lib/stack/taxonomy/index.js index b9d03df5..ccac2296 100644 --- a/lib/stack/taxonomy/index.js +++ b/lib/stack/taxonomy/index.js @@ -5,9 +5,14 @@ import { fetch, query, update, - deleteEntity + deleteEntity, + upload, + parseData } from '../../entity' import { Terms, TermsCollection } from './terms' +import FormData from 'form-data' +import { createReadStream } from 'fs' +import error from '../../core/contentstackError' export function Taxonomy (http, data = {}) { this.stackHeaders = data.stackHeaders @@ -69,6 +74,36 @@ export function Taxonomy (http, data = {}) { */ this.fetch = fetch(http, 'taxonomy') + /** + * @description The Export taxonomy call is used to export an existing taxonomy. + * @memberof Taxonomy + * @func export + * @returns {Promise} Promise for Taxonomy instance + * @example + * import * as contentstack from '@contentstack/management' + * const client = contentstack.client() + * + * client.stack({ api_key: 'api_key'}).taxonomy('taxonomyUid').export() + * .then((taxonomy) => console.log(taxonomy)) + * + */ + this.export = async () => { + try { + const headers = { + headers: { ...cloneDeep(this.stackHeaders) } + } + const response = await http.get(`${this.urlPath}/export`, headers) + if (response.data) { + return response.data + } else { + throw error(response) + } + } catch (err) { + throw error(err) + } + } + + this.terms = (uid = '') => { const data = { stackHeaders: this.stackHeaders } data.taxonomy_uid = this.uid @@ -113,6 +148,42 @@ export function Taxonomy (http, data = {}) { * .then((taxonomies) => console.log(taxonomies) */ this.query = query({ http: http, wrapperCollection: TaxonomyCollection }) + + /** + * @description The 'Import taxonomy' import a single entry by uploading JSON or CSV files. + * @memberof Taxonomy + * @func import + * @param {String} data.taxonomy path to file + * @example + * import * as contentstack from '@contentstack/management' + * const client = contentstack.client() + * + * const data = { + * taxonomy: 'path/to/file.json', + * } + * // Import a Taxonomy + * client.stack({ api_key: 'api_key'}).taxonomy().import(data) + * .then((taxonomy) => console.log(taxonomy)) + */ + this.import = async function (data, params = {}) { + try { + const response = await upload({ + http: http, + urlPath: `${this.urlPath}/import`, + stackHeaders: this.stackHeaders, + formData: createFormData(data), + params: params + }) + if (response.data) { + return new this.constructor(http, parseData(response, this.stackHeaders)) + } else { + throw error(response) + } + } catch (err) { + throw error(err) + } + } + } } export function TaxonomyCollection (http, data) { @@ -122,3 +193,12 @@ export function TaxonomyCollection (http, data) { }) return taxonomyCollection } + +export function createFormData (data) { + return () => { + const formData = new FormData() + const uploadStream = createReadStream(data.taxonomy) + formData.append('taxonomy', uploadStream) + return formData + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4c8de3e7..e723019e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,6 +45,7 @@ "jest": "^28.1.0", "jsdoc": "^4.0.2", "mocha": "^9.2.2", + "mocha-html-reporter": "^0.0.1", "mochawesome": "^7.1.3", "multiparty": "^4.2.3", "nock": "^10.0.6", @@ -10213,6 +10214,15 @@ "url": "https://opencollective.com/mochajs" } }, + "node_modules/mocha-html-reporter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/mocha-html-reporter/-/mocha-html-reporter-0.0.1.tgz", + "integrity": "sha512-AqkAOBOm5/V9arNsb69H+5NhFKM8w/M00882czB9S07dc/eWhodBuGUcp6ZbZBapKZ+OY8YVv7+aAIWUuSeEoQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/mocha/node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -21441,6 +21451,12 @@ } } }, + "mocha-html-reporter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/mocha-html-reporter/-/mocha-html-reporter-0.0.1.tgz", + "integrity": "sha512-AqkAOBOm5/V9arNsb69H+5NhFKM8w/M00882czB9S07dc/eWhodBuGUcp6ZbZBapKZ+OY8YVv7+aAIWUuSeEoQ==", + "dev": true + }, "mochawesome": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-7.1.3.tgz", diff --git a/package.json b/package.json index 6eede519..83438772 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/management", - "version": "1.14.1", + "version": "1.15.0", "description": "The Content Management API is used to manage the content of your Contentstack account", "main": "./dist/node/contentstack-management.js", "browser": "./dist/web/contentstack-management.js", @@ -30,8 +30,8 @@ "buildnativescript": "webpack --config webpack/webpack.nativescript.js --mode production", "buildweb": "webpack --config webpack/webpack.web.js --mode production", "test": "npm run test:api && npm run test:unit", - "test:sanity": "BABEL_ENV=test nyc --reporter=html --reporter=text mocha --require @babel/register ./test/sanity-check/sanity.js -t 30000 --reporter mochawesome --require babel-polyfill", - "test:sanity-report": "node sanity-report.mjs", + "test:sanity": "BABEL_ENV=test nyc --reporter=html mocha --require @babel/register ./test/sanity-check/sanity.js -t 30000 --reporter mochawesome --require babel-polyfill --reporter-options reportDir=mochawesome-report,reportFilename=mochawesome.json && marge mochawesome-report/mochawesome.json -f sanity-report.html --inline", + "test:sanity-report": "marge mochawesome-report/mochawesome.json -f sanity-report.html --inline && node sanity-report.mjs", "test:api": "BABEL_ENV=test nyc --reporter=html --reporter=text mocha --require @babel/register ./test/test.js -t 30000 --reporter mochawesome --require babel-polyfill", "test:unit": "BABEL_ENV=test nyc --reporter=html --reporter=text mocha --require @babel/register ./test/unit/index.js -t 30000 --reporter mochawesome --require babel-polyfill", "test:unit:report:json": "BABEL_ENV=test nyc --reporter=clover --reporter=text mocha --require @babel/register ./test/unit/index.js -t 30000 --reporter json --reporter-options output=report.json --require babel-polyfill", @@ -92,6 +92,7 @@ "jest": "^28.1.0", "jsdoc": "^4.0.2", "mocha": "^9.2.2", + "mocha-html-reporter": "^0.0.1", "mochawesome": "^7.1.3", "multiparty": "^4.2.3", "nock": "^10.0.6", diff --git a/sanity-report.mjs b/sanity-report.mjs index 224457ae..2014ae87 100644 --- a/sanity-report.mjs +++ b/sanity-report.mjs @@ -6,29 +6,32 @@ dotenv.config() const mochawesomeJsonOutput = fs.readFileSync('./mochawesome-report/mochawesome.json', 'utf-8') const mochawesomeReport = JSON.parse(mochawesomeJsonOutput) +const report = `./mochawesome-report/sanity-report.html` const totalSuites = mochawesomeReport.stats.suites const totalTests = mochawesomeReport.stats.tests const passedTests = mochawesomeReport.stats.passes const failedTests = mochawesomeReport.stats.failures const pendingTests = mochawesomeReport.stats.pending -const durationInSeconds = mochawesomeReport.stats.duration / 1000 +let durationInSeconds = mochawesomeReport.stats.duration / 1000 +const durationInMinutes = Math.floor(durationInSeconds / 60) +durationInSeconds %= 60 console.log(`Total Suites: ${totalSuites}`) console.log(`Total Tests: ${totalTests}`) console.log(`Passed Tests: ${passedTests}`) console.log(`Failed Tests: ${failedTests}`) console.log(`Pending Tests: ${pendingTests}`) -console.log(`Total Duration: ${durationInSeconds.toFixed(2)} seconds`) +console.log(`Total Duration: ${durationInMinutes}m ${durationInSeconds.toFixed(2)}s`) const slackMessage = ` *Test Summary* -Total Suites: ${totalSuites} -Total Tests: ${totalTests} -Passed Tests: ${passedTests} -Failed Tests: ${failedTests} -Pending Tests: ${pendingTests} -Total Duration: ${durationInSeconds.toFixed(2)} seconds +• Total Suites: *${totalSuites}* +• Total Tests: *${totalTests}* +• Passed Tests: *${passedTests}* +• Failed Tests: *${failedTests}* +• Pending Tests: *${pendingTests}* +• Total Duration: *${durationInMinutes}m ${durationInSeconds.toFixed(2)}s* ` const app = new Slack.App({ @@ -36,12 +39,20 @@ const app = new Slack.App({ signingSecret: process.env.SLACK_SIGNING_SECRET }) -async function publishMessage (text) { +async function publishMessage (text, report) { await app.client.chat.postMessage({ token: process.env.SLACK_BOT_TOKEN, channel: process.env.SLACK_CHANNEL, text: text }) + await app.client.files.upload({ + token: process.env.SLACK_BOT_TOKEN, + channels: process.env.SLACK_CHANNEL, + initial_comment: '*Here is the report generated*', + filetype: 'html', + filename: 'sanity-report.html', + file: fs.createReadStream(report) + }) } -publishMessage(slackMessage) +publishMessage(slackMessage, report) diff --git a/test/sanity-check/api/create-test.js b/test/sanity-check/api/create-test.js new file mode 100644 index 00000000..e69de29b diff --git a/test/sanity-check/api/delete-test.js b/test/sanity-check/api/delete-test.js new file mode 100644 index 00000000..de5f8739 --- /dev/null +++ b/test/sanity-check/api/delete-test.js @@ -0,0 +1,68 @@ +import { expect } from 'chai' +import { describe, it, setup } from 'mocha' +import { jsonReader } from '../utility/fileOperations/readwrite' +import { environmentCreate, environmentProdCreate } from '../mock/environment.js' +import { contentstackClient } from '../utility/ContentstackClient.js' + +let client = {} + +describe('Delete Environment api Test', () => { + setup(() => { + const user = jsonReader('loggedinuser.json') + client = contentstackClient(user.authtoken) + }) + it('should delete an environment', done => { + makeEnvironment(environmentCreate.environment.name) + .delete() + .then((data) => { + expect(data.notice).to.be.equal('Environment deleted successfully.') + done() + }) + .catch(done) + }) + + it('should delete the prod environment', done => { + makeEnvironment(environmentProdCreate.environment.name) + .delete() + .then((data) => { + expect(data.notice).to.be.equal('Environment deleted successfully.') + done() + }) + .catch(done) + }) +}) + +describe('Delete Locale api Test', () => { + setup(() => { + const user = jsonReader('loggedinuser.json') + client = contentstackClient(user.authtoken) + }) + + it('should delete language: Hindi - India', done => { + makeLocale('hi-in') + .delete() + .then((data) => { + expect(data.notice).to.be.equal('Language removed successfully.') + done() + }) + .catch(done) + }) + + it('should delete language: English - Austria', done => { + makeLocale('en-at') + .delete() + .then((data) => { + expect(data.notice).to.be.equal('Language removed successfully.') + done() + }) + .catch(done) + }) +}) + +function makeEnvironment (uid = null) { + return client.stack({ api_key: process.env.API_KEY }).environment(uid) +} + +function makeLocale (uid = null) { + return client.stack({ api_key: process.env.API_KEY }).locale(uid) +} diff --git a/test/sanity-check/api/locale-test.js b/test/sanity-check/api/locale-test.js new file mode 100644 index 00000000..913a5188 --- /dev/null +++ b/test/sanity-check/api/locale-test.js @@ -0,0 +1,127 @@ +import { expect } from 'chai' +import { describe, it, setup } from 'mocha' +import { jsonReader } from '../utility/fileOperations/readwrite' +import { contentstackClient } from '../utility/ContentstackClient.js' + +let client = {} + +describe('Locale api Test', () => { + setup(() => { + const user = jsonReader('loggedinuser.json') + client = contentstackClient(user.authtoken) + }) + + it('should add a language English - Austria', done => { + makeLocale() + .create({ locale: { code: 'en-at' } }) + .then((locale) => { + expect(locale.code).to.be.equal('en-at') + expect(locale.name).to.be.equal('English - Austria') + expect(locale.fallback_locale).to.be.equal('en-us') + expect(locale.uid).to.be.not.equal(null) + done() + }) + .catch(done) + }) + + it('should add a language Hindi - India', done => { + makeLocale() + .create({ locale: { code: 'hi-in' } }) + .then((locale) => { + expect(locale.code).to.be.equal('hi-in') + expect(locale.name).to.be.equal('Hindi - India') + expect(locale.fallback_locale).to.be.equal('en-us') + expect(locale.uid).to.be.not.equal(null) + done() + }) + .catch(done) + }) + + it('should add a language Marathi - India with Fallback en-at', done => { + makeLocale() + .create({ locale: { code: 'mr-in', fallback_locale: 'en-at' } }) + .then((locale) => { + expect(locale.code).to.be.equal('mr-in') + expect(locale.name).to.be.equal('Marathi - India') + expect(locale.fallback_locale).to.be.equal('en-at') + expect(locale.uid).to.be.not.equal(null) + done() + }) + .catch(done) + }) + + it('should get a all languages', done => { + makeLocale() + .query() + .find() + .then((locales) => { + locales.items.forEach((locale) => { + expect(locale.code).to.be.not.equal(null) + expect(locale.name).to.be.not.equal(null) + expect(locale.uid).to.be.not.equal(null) + }) + done() + }) + .catch(done) + }) + + it('should query a language Hindi - India', done => { + makeLocale() + .query({ query: { name: 'Hindi - India' } }) + .find() + .then((locales) => { + locales.items.forEach((locale) => { + expect(locale.code).to.be.equal('hi-in') + expect(locale.name).to.be.equal('Hindi - India') + expect(locale.fallback_locale).to.be.equal('en-us') + expect(locale.uid).to.be.not.equal(null) + }) + done() + }) + .catch(done) + }) + + it('should get a language Hindi - India', done => { + makeLocale('hi-in') + .fetch() + .then((locale) => { + expect(locale.code).to.be.equal('hi-in') + expect(locale.name).to.be.equal('Hindi - India') + expect(locale.fallback_locale).to.be.equal('en-us') + expect(locale.uid).to.be.not.equal(null) + done() + }) + .catch(done) + }) + + it('should get and update a language Hindi - India', done => { + makeLocale('hi-in') + .fetch() + .then((locale) => { + locale.fallback_locale = 'en-at' + return locale.update() + }) + .then((locale) => { + expect(locale.code).to.be.equal('hi-in') + expect(locale.name).to.be.equal('Hindi - India') + expect(locale.fallback_locale).to.be.equal('en-at') + expect(locale.uid).to.be.not.equal(null) + done() + }) + .catch(done) + }) + + it('should delete language: Hindi - India', done => { + makeLocale('mr-in') + .delete() + .then((data) => { + expect(data.notice).to.be.equal('Language removed successfully.') + done() + }) + .catch(done) + }) +}) + +function makeLocale (uid = null) { + return client.stack({ api_key: process.env.API_KEY }).locale(uid) +} diff --git a/test/sanity-check/sanity.js b/test/sanity-check/sanity.js index 960b4567..13843af7 100644 --- a/test/sanity-check/sanity.js +++ b/test/sanity-check/sanity.js @@ -1,6 +1,7 @@ require('./api/user-test') require('./api/organization-test') require('./api/stack-test') +require('./api/locale-test') require('./api/environment-test') require('./api/contentType-test') require('./api/asset-test') @@ -10,3 +11,4 @@ require('./api/branchAlias-test') require('./api/contentType-delete-test') require('./api/taxonomy-test') require('./api/terms-test') +require('./api/delete-test')