From 010f95065ae385723fb172c791f2ab2bc298e1d7 Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Fri, 19 Jan 2024 18:51:31 +0530 Subject: [PATCH 1/4] test: Added locale test suit and delete test suit to sanity folder --- package.json | 5 +- 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 + 6 files changed, 221 insertions(+), 12 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/package.json b/package.json index 6eede519..d4b6711b 100644 --- a/package.json +++ b/package.json @@ -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') From 0c4641c3f6ece5bf6b1db6f00b79ad4aa4614b14 Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Fri, 19 Jan 2024 19:03:20 +0530 Subject: [PATCH 2/4] chore: updated package-lock file --- package-lock.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) 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", From bf8d05f5d2f868612566a8d5e8baa95a45209a63 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:30:42 +0530 Subject: [PATCH 3/4] Added taxonomy import/export support (#112) Co-authored-by: Nadeem <110535104+nadeem-cs@users.noreply.github.com> --- CHANGELOG.md | 10 +++-- README.md | 2 +- lib/stack/taxonomy/index.js | 82 ++++++++++++++++++++++++++++++++++++- package.json | 2 +- 4 files changed, 89 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23923286..02ac5b48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,13 @@ # Changelog -## [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.15.0](https://github.com/contentstack/contentstack-management-javascript/tree/v1.15.0) (2024-01-23) + - Feature + - Taxonomy Import/Export feature added ## [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/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.json b/package.json index d4b6711b..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", From 7b4bb833ea19b81a89d3ecb7e1548244e11f2aa5 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:37:19 +0530 Subject: [PATCH 4/4] Validating the object when update the entries with assets (#114) Co-authored-by: Nadeem <110535104+nadeem-cs@users.noreply.github.com> --- CHANGELOG.md | 3 +++ lib/entity.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02ac5b48..d28b6df0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## [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 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 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) {