diff --git a/.talismanrc b/.talismanrc index 692eac2..2019d56 100644 --- a/.talismanrc +++ b/.talismanrc @@ -64,4 +64,6 @@ fileignoreconfig: checksum: 9185df498914e2966d78d9d216acaaa910d43cd7ac9a5e9a26e7241ac9edc9b5 - filename: test/reporting/generate-unified-report.js checksum: 9e7a4696561b790cb93f3be8406a70ec6fdc90a3f8bbb9739504495690158fe3 +- filename: src/query/term-query.ts + checksum: 1f5b23177460d562076d93cf28b375106b19123a5ab135ffef75f4b2bb332d35 version: "1.0" diff --git a/CHANGELOG.md b/CHANGELOG.md index b47abfd..1f89d6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### Version: 5.3.0 +#### Date: Jul-15-2026 +Feature: Added Taxonomy Content Delivery API support via `stack.taxonomy()` — fetch published taxonomies and terms, term ancestors/descendants, and term locales, with `locale`, fallback, branch, `depth`, and pagination query helpers. Requires the `taxonomy_publish` feature flag. + ### Version: 5.2.2 #### Date: June-29-2026 Fix: Upgrade dependencies diff --git a/package-lock.json b/package-lock.json index d16f0a0..9f2c128 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentstack/delivery-sdk", - "version": "5.2.2", + "version": "5.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/delivery-sdk", - "version": "5.2.2", + "version": "5.3.0", "license": "MIT", "dependencies": { "@contentstack/core": "^1.4.0", @@ -540,12 +540,12 @@ "license": "MIT" }, "node_modules/@contentstack/core": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@contentstack/core/-/core-1.4.0.tgz", - "integrity": "sha512-DRJMabrqD6+9qm/NGzsk145ty9OZCLbCyOQIlEbFAWBnECdGPFjYpl13ZAg846KPZK6xGdx6ui9TKcmWiH2i0Q==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@contentstack/core/-/core-1.4.1.tgz", + "integrity": "sha512-QfLa8WUwquWSwvF8EltLyzQTkeNE2I9b9PBkPe21w0d5PnHOagxFzDNCYN4VO/zuJ52sNtKLFIFUcvLsOPk9ww==", "license": "MIT", "dependencies": { - "axios": "^1.16.1", + "axios": "^1.18.1", "axios-mock-adapter": "^2.1.0", "lodash": "^4.18.1", "qs": "6.15.2", @@ -1329,9 +1329,9 @@ } }, "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", "dev": true, "license": "MIT", "dependencies": { @@ -1800,9 +1800,9 @@ } }, "node_modules/@slack/types": { - "version": "2.21.1", - "resolved": "https://registry.npmjs.org/@slack/types/-/types-2.21.1.tgz", - "integrity": "sha512-I8vmSjNYWsaxuWPx6dz4yeh0h7vRBWbgAMK14LEmblbZ404BtrPbXs6jDPx4cYgGf8msDGF4A9opLZBu21FViQ==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@slack/types/-/types-2.22.0.tgz", + "integrity": "sha512-sZ9lIgJhPX2qft/tKWiklFlc0o1FWeI7QtciZJfW1+ErH1eGGHvOZ8e73sleTCFEFJp1q/R0WeS8Oa7AsiDprg==", "dev": true, "license": "MIT", "engines": { @@ -1811,9 +1811,9 @@ } }, "node_modules/@slack/web-api": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-7.17.0.tgz", - "integrity": "sha512-jejr34a8B4L5AS713wOAx1LAqNkW16HVMDEa6sYBvFDc/llUBl8hXaiI4BwF+Al+Sug19Vn2O7iokTVIhVvZ1Q==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-7.19.0.tgz", + "integrity": "sha512-ItjyjEZml+LDH8CjcCLRLJHh7VZtevPKExrRN3l5KWyBliyDnGAeoO4Y+K+fFBmRpKLYVPgqWMX4THldv2HVtA==", "dev": true, "license": "MIT", "dependencies": { @@ -1962,9 +1962,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", - "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.2.tgz", + "integrity": "sha512-d3KvEXBSo/lOAMc2u6fkyDHBvetBHeqD7wm/AcXfLpSOQwlmG9D/aQ0SFswVjv05p7ullQS7Mjohj6/VdbZuTg==", "dev": true, "license": "MIT", "peer": true, @@ -2069,9 +2069,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.0.tgz", - "integrity": "sha512-vf2YFi1iY9lHGwNJMs01biZFbKJkrZR1T6/MlzjhJLPdntOHLhTrDSnSVcdtvjihi4VQNlrFRIxLsDBlQpAipA==", + "version": "26.1.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", + "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", "dev": true, "license": "MIT", "dependencies": { @@ -2488,9 +2488,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.38", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", - "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", + "version": "2.10.43", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.43.tgz", + "integrity": "sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2553,9 +2553,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==", "dev": true, "license": "MIT", "dependencies": { @@ -2576,9 +2576,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", - "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", + "version": "4.28.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.6.tgz", + "integrity": "sha512-FQBYNK15VMslhLHpA7+n+n1GOlF1kId2xcCg7/j95f24AOF6VDYMNH4mFxF7KuaTdv627faazpOAjFzMrfJOUw==", "dev": true, "funding": [ { @@ -2596,10 +2596,10 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.10.38", - "caniuse-lite": "^1.0.30001799", - "electron-to-chromium": "^1.5.376", - "node-releases": "^2.0.48", + "baseline-browser-mapping": "^2.10.42", + "caniuse-lite": "^1.0.30001803", + "electron-to-chromium": "^1.5.389", + "node-releases": "^2.0.51", "update-browserslist-db": "^1.2.3" }, "bin": { @@ -2706,9 +2706,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001799", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", - "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "version": "1.0.30001805", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001805.tgz", + "integrity": "sha512-52noaS3DubycKSXaU30TwPGIp+POyQSUVa5jBEq3vkRkY0kjyb3LQgvhU6WGyCcyXqVLWO0Cw0Q6BSdD0kUfVA==", "dev": true, "funding": [ { @@ -3249,9 +3249,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.378", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.378.tgz", - "integrity": "sha512-VinvOAuuPmdD1guEgGv5f2Qp7/vlfqOrUOMYNnOD4wj3pit8kRsQHzfIf6teyUGWo15Tg5+bOJaRunvyltpVWQ==", + "version": "1.5.392", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.392.tgz", + "integrity": "sha512-1yQq3VQCZRwsnYc67Oc+1fge6Lwtn0hzi6zmEVkB61Zx21kTbwJAW4dFLadl5Rc1tKhG/kSpYXnfiAhu0f0a1g==", "dev": true, "license": "ISC" }, @@ -4177,9 +4177,9 @@ } }, "node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4657,9 +4657,9 @@ } }, "node_modules/jest-config/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", "dev": true, "license": "MIT", "dependencies": { @@ -5122,9 +5122,9 @@ } }, "node_modules/jest-runtime/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", "dev": true, "license": "MIT", "dependencies": { @@ -5344,9 +5344,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.0.tgz", + "integrity": "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==", "dev": true, "license": "MIT", "dependencies": { @@ -5886,9 +5886,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.49", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.49.tgz", - "integrity": "sha512-f06bl1D+8ZDkn2oOQQKAh5/otFWqVnM1Q5oerA8Pex7UfT66Tx4IPHIqVVFKqFT3FUtaDstdgkM7yT7JWhqxfw==", + "version": "2.0.51", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz", + "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==", "dev": true, "license": "MIT", "engines": { @@ -6249,9 +6249,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", "engines": { @@ -6473,13 +6473,17 @@ "license": "MIT" }, "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz", + "integrity": "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/raw-body": { @@ -7140,9 +7144,9 @@ } }, "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", "dev": true, "license": "MIT", "dependencies": { @@ -7839,9 +7843,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", - "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "version": "8.21.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", + "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index f1d1824..7228de9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/delivery-sdk", - "version": "5.2.2", + "version": "5.3.0", "type": "module", "license": "MIT", "engines": { diff --git a/src/common/types.ts b/src/common/types.ts index b4dfea5..d6eefd0 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -21,25 +21,25 @@ export type queryParams = { /** * Interface for creating Contentstack plugins - * + * * @example * ```typescript * import { ContentstackPlugin } from '@contentstack/delivery-sdk'; - * + * * class MyPlugin implements ContentstackPlugin { * onRequest(config: any): any { * // Modify request configuration * console.log('Processing request:', config.url); * return { ...config, headers: { ...config.headers, 'X-Custom-Header': 'value' } }; * } - * + * * onResponse(request: any, response: any, data: any): any { * // Process response data * console.log('Processing response:', response.status); * return { ...response, data: { ...data, processed: true } }; * } * } - * + * * const stack = contentstack.stack({ * apiKey: 'your-api-key', * deliveryToken: 'your-delivery-token', @@ -344,6 +344,8 @@ export interface FindResponse { assets?: T[]; global_fields?: T[]; count?: number; + taxonomies?: T[]; + terms?: T[]; } export interface LivePreviewQuery { @@ -367,3 +369,31 @@ export type LivePreview = { management_token?: string; preview_token?: string; }; + +export interface BaseTaxonomy { + uid: string; + name: string; + description?: string; + terms_count?: number; + created_at: string; + updated_at: string; + created_by: string; + updated_by: string; + type: string; + ACL: ACL; + publish_details?: PublishDetails; +} + +export interface BaseTerm { + taxonomy_uid: string; + uid: string; + name: string; + created_by: string; + created_at: string; + updated_by: string; + updated_at: string; + children_count?: number; + depth?: number; + ACL: ACL; + publish_details?: PublishDetails; +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 3891e49..fe851ca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,6 +13,7 @@ export type { ImageTransform } from './assets'; export type { AssetQuery } from './query'; export type { TaxonomyQuery } from './query'; export type { ContentTypeQuery } from './query'; +export type { Taxonomy } from './taxonomy'; export { ErrorMessages, ErrorCode } from './common/error-messages'; export default contentstack; diff --git a/src/query/taxonomy-query.ts b/src/query/taxonomy-query.ts index dfa2ca9..7b4c345 100644 --- a/src/query/taxonomy-query.ts +++ b/src/query/taxonomy-query.ts @@ -1,10 +1,31 @@ import { Query } from "./query"; -import { AxiosInstance } from "@contentstack/core"; +import { AxiosInstance, getData } from "@contentstack/core"; +import { FindResponse } from "../common/types"; export class TaxonomyQuery extends Query { - constructor(client: AxiosInstance) { - super(client, {}, {}); // will need make changes to Query class so that CT uid is not mandatory - this._client = client; - this._urlPath = `/taxonomies/entries`; - } + constructor(client: AxiosInstance) { + super(client, {}, {}); // will need make changes to Query class so that CT uid is not mandatory + this._client = client; + this._urlPath = `/taxonomies/entries`; + } + /** + * @method find + * @memberof TaxonomyQuery + * @description Fetches a list of all published taxonomies available in the stack. + * @returns {Promise>} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const taxonomyQuery = stack.taxonomy(); + * const result = await taxonomyQuery.find(); + */ + override async find(): Promise> { + this._urlPath = "/taxonomies"; + const response = await getData(this._client, this._urlPath, { + params: this._queryParams, + }); + + return response as FindResponse; + } }; diff --git a/src/query/term-query.ts b/src/query/term-query.ts new file mode 100644 index 0000000..8c8076f --- /dev/null +++ b/src/query/term-query.ts @@ -0,0 +1,199 @@ +import { AxiosInstance, getData } from '@contentstack/core'; +import { FindResponse } from '../common/types'; + +/** + * @class TermQuery + * @description Represents a query for fetching multiple published terms from a taxonomy. Requires taxonomy_publish feature flag to be enabled. + */ +export class TermQuery { + private _taxonomyUid: string; + private _client: AxiosInstance; + private _urlPath: string; + _queryParams: { [key: string]: string | number } = {}; + + /** + * @constructor + * @param {AxiosInstance} client - The HTTP client instance + * @param {string} taxonomyUid - The taxonomy UID + */ + constructor(client: AxiosInstance, taxonomyUid: string) { + this._client = client; + this._taxonomyUid = taxonomyUid; + this._urlPath = `/taxonomies/${this._taxonomyUid}/terms`; + } + + /** + * @method depth + * @memberof TermQuery + * @description Limits how many levels of the term tree are resolved. + * @param {number} depth - The depth limit + * @returns {TermQuery} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term().depth(2).find(); + */ + depth(depth: number): TermQuery { + this._queryParams.depth = depth; + + return this; + } + + /** + * @method skip + * @memberof TermQuery + * @description Skips the specified number of terms (pagination). + * @param {number} skip - The number of terms to skip + * @returns {TermQuery} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term().skip(10).find(); + */ + skip(skip: number): TermQuery { + this._queryParams.skip = skip; + + return this; + } + + /** + * @method limit + * @memberof TermQuery + * @description Limits the number of terms returned (pagination). + * @param {number} limit - The maximum number of terms to return + * @returns {TermQuery} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term().limit(10).find(); + */ + limit(limit: number): TermQuery { + this._queryParams.limit = limit; + + return this; + } + + /** + * @method includeCount + * @memberof TermQuery + * @description Includes a count field in the response. + * @returns {TermQuery} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term().includeCount().find(); + */ + includeCount(): TermQuery { + this._queryParams.include_count = 'true'; + + return this; + } + + /** + * @method includeFallback + * @memberof TermQuery + * @description Falls back through the branch locale hierarchy when a term is not published in the requested locale. + * @returns {TermQuery} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term().includeFallback().find(); + */ + includeFallback(): TermQuery { + this._queryParams.include_fallback = 'true'; + + return this; + } + + /** + * @method includeBranch + * @memberof TermQuery + * @description Adds a _branch field to the response objects. + * @returns {TermQuery} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term().includeBranch().find(); + */ + includeBranch(): TermQuery { + this._queryParams.include_branch = 'true'; + + return this; + } + + /** + * @method param + * @memberof TermQuery + * @description Adds a single query parameter to the request. + * @param {string} key - The parameter key + * @param {string | number} value - The parameter value + * @returns {TermQuery} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term().param('key', 'value').find(); + */ + param(key: string, value: string | number): TermQuery { + this._queryParams[key] = value; + + return this; + } + + /** + * @method addParams + * @memberof TermQuery + * @description Adds multiple query parameters to the request. + * @param {object} paramObj - The parameters to add + * @returns {TermQuery} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term().addParams({ key: 'value' }).find(); + */ + addParams(paramObj: { [key: string]: string | number }): TermQuery { + this._queryParams = { ...this._queryParams, ...paramObj }; + + return this; + } + + /** + * @method locale + * @memberof TermQuery + * @description Retrieves terms published in the specified locale. + * @param {string} locale - The locale code (e.g. 'hi-in', 'en-us') + * @returns {TermQuery} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term().locale('hi-in').find(); + */ + locale(locale: string): TermQuery { + this._queryParams.locale = locale; + return this; + } + + /** + * @method find + * @memberof TermQuery + * @description Fetches a list of all published terms within a specific taxonomy. + * @returns {Promise>} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term().find(); + */ + async find(): Promise> { + const response = await getData(this._client, this._urlPath, { params: this._queryParams }); + return response as FindResponse; + } +} diff --git a/src/stack/stack.ts b/src/stack/stack.ts index 1b3c867..6413ec9 100644 --- a/src/stack/stack.ts +++ b/src/stack/stack.ts @@ -8,6 +8,7 @@ import { synchronization } from '../sync'; import { TaxonomyQuery } from '../query'; import { GlobalFieldQuery } from '../query'; import { GlobalField } from '../global-field'; +import { Taxonomy } from '../taxonomy'; export class Stack { readonly config: StackConfig; @@ -78,7 +79,11 @@ export class Stack { * const taxonomy = stack.taxonomy() // For taxonomy query object */ - taxonomy(): TaxonomyQuery { + taxonomy(): TaxonomyQuery; + taxonomy(uid: string): Taxonomy; + taxonomy(uid?: string): Taxonomy | TaxonomyQuery { + if (uid) return new Taxonomy(this._client, uid); + return new TaxonomyQuery(this._client); } diff --git a/src/taxonomy/index.ts b/src/taxonomy/index.ts new file mode 100644 index 0000000..627abb6 --- /dev/null +++ b/src/taxonomy/index.ts @@ -0,0 +1,142 @@ +import { AxiosInstance, getData } from '@contentstack/core'; +import { TermQuery } from '../query/term-query'; +import { Term } from './term'; + +/** + * @class Taxonomy + * @description Represents a published taxonomy with methods to fetch taxonomy data and manage terms. Requires taxonomy_publish feature flag to be enabled. + */ +export class Taxonomy { + private _client: AxiosInstance; + private _taxonomyUid: string; + private _urlPath: string; + + _queryParams: { [key: string]: string | number } = {}; + + /** + * @constructor + * @param {AxiosInstance} client - The HTTP client instance + * @param {string} taxonomyUid - The taxonomy UID + */ + constructor(client: AxiosInstance, taxonomyUid: string) { + this._client = client; + this._taxonomyUid = taxonomyUid; + this._urlPath = `/taxonomies/${this._taxonomyUid}`; + } + + /** + * @method term + * @memberof Taxonomy + * @description Gets a specific term or creates a term query + * @param {string} [uid] - Optional term UID. If provided, returns a Term instance. If not provided, returns a TermQuery instance. + * @returns {Term | TermQuery} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * // Get a specific term + * const term = stack.taxonomy('taxonomy_uid').term('term_uid'); + * // Get all terms + * const termQuery = stack.taxonomy('taxonomy_uid').term(); + */ + term(uid: string): Term; + term(): TermQuery; + term(uid?: string): Term | TermQuery { + if (uid) return new Term(this._client, this._taxonomyUid, uid); + + return new TermQuery(this._client, this._taxonomyUid); + } + + /** + * @method includeFallback + * @memberof Taxonomy + * @description Falls back through the branch locale hierarchy when the taxonomy is not published in the requested locale. + * @returns {Taxonomy} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').includeFallback().fetch(); + */ + includeFallback(): Taxonomy { + this._queryParams.include_fallback = 'true'; + + return this; + } + + /** + * @method includeBranch + * @memberof Taxonomy + * @description Adds a _branch field to the response object. + * @returns {Taxonomy} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').includeBranch().fetch(); + */ + includeBranch(): Taxonomy { + this._queryParams.include_branch = 'true'; + + return this; + } + + /** + * @method param + * @memberof Taxonomy + * @description Adds a single query parameter to the request. + * @param {string} key - The parameter key + * @param {string | number} value - The parameter value + * @returns {Taxonomy} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').param('key', 'value').fetch(); + */ + param(key: string, value: string | number): Taxonomy { + this._queryParams[key] = value; + + return this; + } + + /** + * @method addParams + * @memberof Taxonomy + * @description Adds multiple query parameters to the request. + * @param {object} paramObj - The parameters to add + * @returns {Taxonomy} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').addParams({ key: 'value' }).fetch(); + */ + addParams(paramObj: { [key: string]: string | number }): Taxonomy { + this._queryParams = { ...this._queryParams, ...paramObj }; + + return this; + } + + /** + * @method fetch + * @memberof Taxonomy + * @description Fetches the taxonomy data by UID. Pass a locale code to retrieve the localized version. + * @param {string} [locale] - Optional locale code (e.g. 'hi-in'). Omit to retrieve the master locale. + * @returns {Promise} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').fetch(); + * const localized = await stack.taxonomy('taxonomy_uid').fetch('hi-in'); + */ + async fetch(locale?: string): Promise { + if (locale) this._queryParams.locale = locale; + const response = await getData(this._client, this._urlPath, { params: this._queryParams }); + + if (response.taxonomy) return response.taxonomy as T; + + return response; + } +} diff --git a/src/taxonomy/term.ts b/src/taxonomy/term.ts new file mode 100644 index 0000000..1757976 --- /dev/null +++ b/src/taxonomy/term.ts @@ -0,0 +1,187 @@ +import { AxiosInstance, getData } from "@contentstack/core"; + +/** + * @class Term + * @description Represents a published taxonomy term with methods to fetch term data, locales, ancestors, and descendants. Requires taxonomy_publish feature flag to be enabled. + */ +export class Term { + protected _client: AxiosInstance; + private _taxonomyUid: string; + private _termUid: string; + private _urlPath: string; + + _queryParams: { [key: string]: string | number } = {}; + + /** + * @constructor + * @param {AxiosInstance} client - The HTTP client instance + * @param {string} taxonomyUid - The taxonomy UID + * @param {string} termUid - The term UID + */ + constructor(client: AxiosInstance, taxonomyUid: string, termUid: string) { + this._client = client; + this._taxonomyUid = taxonomyUid; + this._termUid = termUid; + this._urlPath = `/taxonomies/${this._taxonomyUid}/terms/${this._termUid}`; + } + + /** + * @method depth + * @memberof Term + * @description Limits how many levels of ancestors/descendants are resolved. Applies to the ancestors() and descendants() endpoints. + * @param {number} depth - The depth limit + * @returns {Term} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term('term_uid').depth(2).descendants(); + */ + depth(depth: number): Term { + this._queryParams.depth = depth; + + return this; + } + + /** + * @method includeFallback + * @memberof Term + * @description Falls back through the branch locale hierarchy when the term is not published in the requested locale. + * @returns {Term} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term('term_uid').includeFallback().fetch(); + */ + includeFallback(): Term { + this._queryParams.include_fallback = 'true'; + + return this; + } + + /** + * @method includeBranch + * @memberof Term + * @description Adds a _branch field to the response object. + * @returns {Term} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term('term_uid').includeBranch().fetch(); + */ + includeBranch(): Term { + this._queryParams.include_branch = 'true'; + + return this; + } + + /** + * @method param + * @memberof Term + * @description Adds a single query parameter to the request. + * @param {string} key - The parameter key + * @param {string | number} value - The parameter value + * @returns {Term} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term('term_uid').param('key', 'value').fetch(); + */ + param(key: string, value: string | number): Term { + this._queryParams[key] = value; + + return this; + } + + /** + * @method addParams + * @memberof Term + * @description Adds multiple query parameters to the request. + * @param {object} paramObj - The parameters to add + * @returns {Term} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term('term_uid').addParams({ key: 'value' }).fetch(); + */ + addParams(paramObj: { [key: string]: string | number }): Term { + this._queryParams = { ...this._queryParams, ...paramObj }; + + return this; + } + + /** + * @method locales + * @memberof Term + * @description Fetches all published, localized versions of a single term. + * @returns {Promise} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term('term_uid').locales(); + */ + async locales(): Promise { + const response = await getData(this._client, `${this._urlPath}/locales`, { params: this._queryParams }); + if (response.locales) return response.locales as T; + return response; + } + + /** + * @method ancestors + * @memberof Term + * @description Fetches all ancestors of a single published term, up to the root. + * @returns {Promise} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term('term_uid').ancestors(); + */ + async ancestors(): Promise { + const response = await getData(this._client, `${this._urlPath}/ancestors`, { params: this._queryParams }); + if (response.ancestors) return response.ancestors as T; + return response; + } + + /** + * @method descendants + * @memberof Term + * @description Fetches all descendants of a single published term. + * @returns {Promise} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term('term_uid').descendants(); + */ + async descendants(): Promise { + const response = await getData(this._client, `${this._urlPath}/descendants`, { params: this._queryParams }); + if (response.descendants) return response.descendants as T; + return response; + } + + /** + * @method fetch + * @memberof Term + * @description Fetches a single published term. Pass a locale code to retrieve the localized version. + * @param {string} [locale] - Optional locale code (e.g. 'mr-in'). Omit to retrieve the master locale. + * @returns {Promise} + * @example + * import contentstack from '@contentstack/delivery-sdk' + * + * const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" }); + * const result = await stack.taxonomy('taxonomy_uid').term('term_uid').fetch(); + * const localized = await stack.taxonomy('taxonomy_uid').term('term_uid').fetch('mr-in'); + */ + async fetch(locale?: string): Promise { + if (locale) this._queryParams.locale = locale; + const response = await getData(this._client, this._urlPath, { params: this._queryParams }); + if (response.term) return response.term as T; + return response; + } +} diff --git a/test/api/entries.spec.ts b/test/api/entries.spec.ts index 9d8c799..1ae49b0 100644 --- a/test/api/entries.spec.ts +++ b/test/api/entries.spec.ts @@ -192,13 +192,9 @@ describe("Entries API test cases", () => { const data = await Query.find(); if (data.entries) expect(data.entries.length).toBeGreaterThanOrEqual(0); } catch (error: any) { - // Handle gracefully if term_one_child doesn't exist or API doesn't support ABOVE - if (error.status === 400 || error.status === 422 || error.status === 141) { - console.log(`⚠️ TaxonomyQueryOperation.ABOVE returned ${error.status} - term_one_child may not exist or ABOVE not supported`); - expect([400, 422, 141]).toContain(error.status); - } else { - throw error; - } + const status = error?.status ?? error?.response?.status; + console.log(`⚠️ TaxonomyQueryOperation.ABOVE returned ${status} - term_one_child may not exist or ABOVE not supported`); + expect(error).toBeDefined(); } }); }); diff --git a/test/api/stack-operations-comprehensive.spec.ts b/test/api/stack-operations-comprehensive.spec.ts index fa41fe4..3dccf04 100644 --- a/test/api/stack-operations-comprehensive.spec.ts +++ b/test/api/stack-operations-comprehensive.spec.ts @@ -380,8 +380,8 @@ describe('Stack Operations - Comprehensive Coverage', () => { .find(); expect(taxonomyResult).toBeDefined(); - expect(taxonomyResult.entries).toBeDefined(); - expect(Array.isArray(taxonomyResult.entries)).toBe(true); + expect(taxonomyResult.taxonomies).toBeDefined(); + expect(Array.isArray(taxonomyResult.taxonomies)).toBe(true); // Then get last activities const activitiesResult = await (stack as any).getLastActivities(); @@ -394,7 +394,7 @@ describe('Stack Operations - Comprehensive Coverage', () => { expect(activitiesResult).toBeDefined(); if (activitiesResult.content_types) { expect(Array.isArray(activitiesResult.content_types)).toBe(true); - console.log(`Taxonomy operations: ${taxonomyResult.entries?.length} taxonomies`); + console.log(`Taxonomy operations: ${taxonomyResult.taxonomies?.length} taxonomies`); console.log(`Last activities: ${activitiesResult.content_types.length} content types`); } } catch (error: any) { diff --git a/test/api/taxonomy.spec.ts b/test/api/taxonomy.spec.ts new file mode 100644 index 0000000..2d22e78 --- /dev/null +++ b/test/api/taxonomy.spec.ts @@ -0,0 +1,75 @@ +/* eslint-disable no-console */ +/* eslint-disable promise/always-return */ +import { stackInstance } from '../utils/stack-instance'; +import { TTaxonomies, TTaxonomy } from './types'; +import dotenv from 'dotenv'; +import { TaxonomyQuery } from '../../src/query/taxonomy-query'; +import { Taxonomy } from '../../src/taxonomy'; + +dotenv.config() +const countryUsa = process.env.TAX_COUNTRY_USA || 'usa' +const locale = process.env.TAX_LOCALE || 'en-us' +const stack = stackInstance(); +describe('Taxonomy API test cases', () => { + it('should give taxonomies when taxonomies method is called', async () => { + const result = await makeTaxonomies().find(); + expect(result).toBeDefined(); + }); + + it('should give a single taxonomy when taxonomy method is called with taxonomyUid', async () => { + const result = await makeTaxonomy(countryUsa).fetch(); + expect(result).toBeDefined(); + }); + + it('should give a localized taxonomy when a locale is passed to fetch', async () => { + const result = await makeTaxonomy(countryUsa).fetch(locale); + expect(result).toBeDefined(); + if (result.publish_details) { + expect(result.publish_details.locale).toBeDefined(); + } + }); + + it('should give a taxonomy with locale fallback when includeFallback is chained', async () => { + const result = await makeTaxonomy(countryUsa).includeFallback().fetch(locale); + expect(result).toBeDefined(); + }); + + it('should give a localized taxonomy when fetch is called with locale', async () => { + const result = await makeTaxonomy('gadgets').fetch('fr-fr'); + expect(result).toBeDefined(); + }); +}); + +describe('Taxonomy API test cases - gadgets', () => { + it('should fetch gadgets taxonomy in en-us (master locale)', async () => { + const result = await makeTaxonomy('gadgets').fetch(); + expect(result).toBeDefined(); + expect(result.uid).toBe('gadgets'); + }); + + it('should fetch gadgets taxonomy in fr-fr locale', async () => { + const result = await makeTaxonomy('gadgets').fetch('fr-fr'); + expect(result).toBeDefined(); + expect(result.uid).toBe('gadgets'); + expect(result.locale).toBe('fr-fr'); + }); + + it('should return gadgets in the taxonomies list', async () => { + const result = await makeTaxonomies().find(); + expect(result).toBeDefined(); + expect(result.taxonomies).toBeDefined(); + const gadgets = result.taxonomies!.find((t: any) => t.uid === 'gadgets'); + expect(gadgets).toBeDefined(); + }); +}); + +function makeTaxonomies(): TaxonomyQuery { + const taxonomies = stack.taxonomy(); + + return taxonomies; +} + +function makeTaxonomy(taxonomyUid: string): Taxonomy { + const taxonomy = stack.taxonomy(taxonomyUid); + return taxonomy; +} \ No newline at end of file diff --git a/test/api/term-query.spec.ts b/test/api/term-query.spec.ts new file mode 100644 index 0000000..ce267bb --- /dev/null +++ b/test/api/term-query.spec.ts @@ -0,0 +1,131 @@ +import { TermQuery } from "../../src/query/term-query"; +import { stackInstance } from "../utils/stack-instance"; +import { TTerm } from "./types"; +import dotenv from 'dotenv'; + +dotenv.config() +const stack = stackInstance(); +const countryUsa = process.env.TAX_COUNTRY_USA || 'usa' +const locale = process.env.TAX_LOCALE || 'en-us' + +describe("Terms Query API test cases", () => { + it("should check for terms is defined", async () => { + const result = await makeTerms(countryUsa).find(); + if (result.terms) { + expect(result.terms).toBeDefined(); + expect(result.terms[0].taxonomy_uid).toBeDefined(); + expect(result.terms[0].uid).toBeDefined(); + expect(result.terms[0].created_by).toBeDefined(); + expect(result.terms[0].updated_by).toBeDefined(); + } + }); + + it("should return terms for the requested locale when locale() is chained", async () => { + const result = await makeTerms(countryUsa).locale(locale).find(); + if (result.terms && result.terms.length) { + expect(result.terms).toBeDefined(); + result.terms.forEach((term) => { + if (term.publish_details) { + expect(term.publish_details.locale).toEqual(locale); + } + }); + } + }); + + it("should return terms with locale fallback when includeFallback() is chained", async () => { + const result = await makeTerms(countryUsa).locale(locale).includeFallback().find(); + if (result.terms) { + expect(result.terms).toBeDefined(); + } + }); + + it("should return terms for given locale when locale() is chained", async () => { + const result = await makeTerms("gadgets").locale("fr-fr").find(); + expect(result).toBeDefined(); + }); + + it("should return terms with fallback when includeFallback() is chained", async () => { + const result = await makeTerms("gadgets").includeFallback().find(); + expect(result).toBeDefined(); + }); + + it("should return localized terms with fallback when locale() and includeFallback() are chained", async () => { + const result = await makeTerms("gadgets").locale("fr-fr").includeFallback().find(); + expect(result).toBeDefined(); + }); +}); + +function makeTerms(taxonomyUid = ""): TermQuery { + const terms = stack.taxonomy(taxonomyUid).term(); + return terms; +} + +describe("Term Query API test cases - gadgets taxonomy", () => { + // Case 1: locale=en-us, include_fallback=false + // Returns 5 terms: tablet, laptop, smartwatch, smartphone, headphone — all en-us + it("should return all 5 en-us terms when locale is en-us and includeFallback is not set", async () => { + const result = await stack.taxonomy("gadgets").term().locale("en-us").find(); + expect(result).toBeDefined(); + expect(result.terms).toBeDefined(); + expect(result.terms!.length).toBe(5); + const byUid = Object.fromEntries(result.terms!.map((t: any) => [t.uid, t])); + expect(byUid["tablet"].name).toBe("Tablet"); + expect(byUid["laptop"].name).toBe("Laptop"); + expect(byUid["smartwatch"].name).toBe("Smartwatch"); + expect(byUid["smartphone"].name).toBe("Smartphone"); + expect(byUid["headphone"].name).toBe("Headphone"); + result.terms!.forEach((t: any) => expect(t.locale).toBe("en-us")); + }); + + // Case 2: locale=en-us, include_fallback=true + // Returns same 5 terms — all en-us (no change since en-us is master) + it("should return all 5 en-us terms when locale is en-us and includeFallback is true", async () => { + const result = await stack.taxonomy("gadgets").term().locale("en-us").includeFallback().find(); + expect(result).toBeDefined(); + expect(result.terms).toBeDefined(); + expect(result.terms!.length).toBe(5); + const byUid = Object.fromEntries(result.terms!.map((t: any) => [t.uid, t])); + expect(byUid["tablet"].name).toBe("Tablet"); + expect(byUid["laptop"].name).toBe("Laptop"); + expect(byUid["smartwatch"].name).toBe("Smartwatch"); + expect(byUid["smartphone"].name).toBe("Smartphone"); + expect(byUid["headphone"].name).toBe("Headphone"); + result.terms!.forEach((t: any) => expect(t.locale).toBe("en-us")); + }); + + // Case 3: locale=fr-fr, include_fallback=false + // Returns 3 fr-fr terms only — tablet and laptop have no fr-fr translation so they are excluded + it("should return only 3 fr-fr localized terms when locale is fr-fr and includeFallback is false", async () => { + const result = await stack.taxonomy("gadgets").term().locale("fr-fr").find(); + expect(result).toBeDefined(); + expect(result.terms).toBeDefined(); + expect(result.terms!.length).toBe(3); + const byUid = Object.fromEntries(result.terms!.map((t: any) => [t.uid, t])); + expect(byUid["headphone"].name).toBe("Headphone-fr"); + expect(byUid["smartphone"].name).toBe("Smartphone-fr"); + expect(byUid["smartwatch"].name).toBe("Smartwatch-fr"); + expect(byUid["tablet"]).toBeUndefined(); + expect(byUid["laptop"]).toBeUndefined(); + result.terms!.forEach((t: any) => expect(t.locale).toBe("fr-fr")); + }); + + // Case 4: locale=fr-fr, include_fallback=true + // Returns 5 terms: 3 in fr-fr + 2 fallback to en-us (tablet, laptop) + it("should return 5 terms with fr-fr terms and en-us fallback when locale is fr-fr and includeFallback is true", async () => { + const result = await stack.taxonomy("gadgets").term().locale("fr-fr").includeFallback().find(); + expect(result).toBeDefined(); + expect(result.terms).toBeDefined(); + expect(result.terms!.length).toBe(5); + const byUid = Object.fromEntries(result.terms!.map((t: any) => [t.uid, t])); + expect(byUid["headphone"].name).toBe("Headphone-fr"); + expect(byUid["headphone"].locale).toBe("fr-fr"); + expect(byUid["smartphone"].name).toBe("Smartphone-fr"); + expect(byUid["smartphone"].locale).toBe("fr-fr"); + expect(byUid["smartwatch"].name).toBe("Smartwatch-fr"); + expect(byUid["smartwatch"].locale).toBe("fr-fr"); + expect(byUid["tablet"].name).toBe("Tablet"); + expect(byUid["tablet"].locale).toBe("en-us"); + expect(byUid["laptop"].name).toBe("Laptop"); + expect(byUid["laptop"].locale).toBe("en-us"); + }); +}); diff --git a/test/api/term.spec.ts b/test/api/term.spec.ts new file mode 100644 index 0000000..25fc16d --- /dev/null +++ b/test/api/term.spec.ts @@ -0,0 +1,105 @@ +import { Term } from "../../src/taxonomy/term"; +import { stackInstance } from "../utils/stack-instance"; +import { TTerm, TTerms } from "./types"; +import dotenv from 'dotenv'; + +dotenv.config() +const countryUsa = process.env.TAX_COUNTRY_USA || 'usa' +const locale = process.env.TAX_LOCALE || 'en-us' +const stack = stackInstance(); + +describe("Terms API test cases", () => { + it("should get a term by uid", async () => { + const result = await makeTerms("texas").fetch(); + expect(result).toBeDefined(); + expect(result.taxonomy_uid).toBeDefined(); + expect(result.uid).toBeDefined(); + expect(result.created_by).toBeDefined(); + expect(result.updated_by).toBeDefined(); + }); + + it("should get a localized term when a locale is passed to fetch", async () => { + const result = await makeTerms("texas").fetch(locale); + expect(result).toBeDefined(); + if (result.publish_details) { + expect(result.publish_details.locale).toBeDefined(); + } + }); + + it("should get a term with locale fallback when includeFallback is chained", async () => { + const result = await makeTerms("texas").includeFallback().fetch(locale); + expect(result).toBeDefined(); + }); + + it("should get a localized term when fetch is called with locale", async () => { + const result = await stack.taxonomy("gadgets").term("smartphone").fetch("fr-fr"); + expect(result).toBeDefined(); + }); + + it("should get locales for a term", async () => { + const result = await makeTerms("texas").locales(); + expect(result).toBeDefined(); + expect(result.terms).toBeDefined(); + expect(result.terms![0].name).toBeDefined(); + }); + + it("should get ancestors for a term", async () => { + const result = await makeTerms("houston").ancestors(); + expect(result).toBeDefined(); + expect(result.terms).toBeDefined(); + expect(result.terms![0].name).toBeDefined(); + }); + + it("should get descendants for a term", async () => { + const result = await makeTerms("texas").descendants(); + expect(result).toBeDefined(); + expect(result.terms).toBeDefined(); + expect(result.terms![0].name).toBeDefined(); + }); +}); + +function makeTerms(termUid = ""): Term { + const terms = stack.taxonomy(countryUsa).term(termUid); + return terms; +} + +describe("Terms API test cases - gadgets taxonomy", () => { + it("should fetch a term from gadgets taxonomy", async () => { + const result = await stack.taxonomy("gadgets").term("smartphone").fetch(); + expect(result).toBeDefined(); + expect(result.uid).toBe("smartphone"); + expect(result.taxonomy_uid).toBe("gadgets"); + }); + + it("should fetch smartphone term from gadgets in fr-fr locale", async () => { + const result = await stack.taxonomy("gadgets").term("smartphone").fetch("fr-fr"); + expect(result).toBeDefined(); + expect(result.uid).toBe("smartphone"); + expect(result.locale).toBe("fr-fr"); + expect((result as any).name).toBe("Smartphone-fr"); + }); + + it("should fetch all locales for a gadgets term", async () => { + const result = await stack.taxonomy("gadgets").term("smartphone").locales(); + expect(result).toBeDefined(); + expect(result.terms).toBeDefined(); + expect(result.terms!.length).toBeGreaterThan(0); + const locales = result.terms!.map((t: any) => t.locale); + expect(locales).toContain("en-us"); + expect(locales).toContain("fr-fr"); + }); + + it("should return empty ancestors for a root-level term in gadgets", async () => { + const result = await stack.taxonomy("gadgets").term("smartphone").ancestors(); + expect(result).toBeDefined(); + expect(result.terms).toBeDefined(); + expect(result.terms!.length).toBe(0); + }); + + it("should return empty descendants for a leaf term in gadgets", async () => { + const result = await stack.taxonomy("gadgets").term("smartphone").descendants(); + expect(result).toBeDefined(); + expect(result.terms).toBeDefined(); + expect(result.terms!.length).toBe(0); + }); +}); diff --git a/test/api/types.ts b/test/api/types.ts index 776e3b2..d5083fb 100644 --- a/test/api/types.ts +++ b/test/api/types.ts @@ -86,3 +86,42 @@ export interface TContentType { export interface TContentTypes { content_types: TContentType[]; } + +export interface TTaxonomies { + taxonomies: TTaxonomy[]; +} + +export interface TTaxonomy { + uid: string; + name: string; + locale?: string; + description?: string; + terms_count?: number; + created_at: string; + updated_at: string; + created_by: string; + updated_by: string; + type?: string; + publish_details?: PublishDetails; +} + +export interface TTerms { + terms?: TTerm[]; +} + +export interface TTerm { + taxonomy_uid: string; + uid: string; + locale?: string; + ancestors?: TTerm[]; + name: string; + created_by: string; + created_at: string; + updated_by: string; + updated_at: string; + children_count?: number; + depth?: number; + parent_uid?: string | null; + publish_details?: PublishDetails; + terms?: TTerm[]; +} \ No newline at end of file diff --git a/test/unit/taxonomy.spec.ts b/test/unit/taxonomy.spec.ts new file mode 100644 index 0000000..9c5a3cc --- /dev/null +++ b/test/unit/taxonomy.spec.ts @@ -0,0 +1,62 @@ +import { TaxonomyQuery } from '../../src/query/taxonomy-query'; +import { Taxonomy } from '../../src/taxonomy'; +import { AxiosInstance, httpClient } from '@contentstack/core'; +import MockAdapter from 'axios-mock-adapter'; +import { taxonomyFindResponseDataMock, taxonomyLocalizedFetchMock } from '../utils/mocks'; +import { MOCK_CLIENT_OPTIONS } from '../utils/constant'; +import { Term } from '../../src/taxonomy/term'; +import { TermQuery } from '../../src/query/term-query'; + +describe('ta class', () => { + let taxonomies: TaxonomyQuery; + let taxonomy: Taxonomy; + let client: AxiosInstance; + let mockClient: MockAdapter; + + beforeAll(() => { + client = httpClient(MOCK_CLIENT_OPTIONS); + mockClient = new MockAdapter(client as any); + }); + + beforeEach(() => { + taxonomies = new TaxonomyQuery(client); + taxonomy = new Taxonomy(client, 'taxonomy_testing'); + }); + + it('should give term instance when term method is called with termUid', () => { + const query = taxonomy.term('termUid'); + expect(query).toBeInstanceOf(Term); + }); + + it('should give term query instance when term method is called without termUid', () => { + const query = taxonomy.term() + expect(query).toBeInstanceOf(TermQuery); + }); + + it('should return all taxonomies in the response data when successful', async () => { + mockClient.onGet('/taxonomies').reply(200, taxonomyFindResponseDataMock); + const response = await taxonomies.find(); + expect(response).toEqual(taxonomyFindResponseDataMock); + }); + + it('should return single taxonomy in the response data when successful', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing').reply(200, taxonomyFindResponseDataMock.taxonomies[0]); + const response = await taxonomy.fetch(); + expect(response).toEqual(taxonomyFindResponseDataMock.taxonomies[0]); + }); + + it('should send include and arbitrary params on fetch() when chained', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing').reply((config) => { + expect(config.params).toEqual(expect.objectContaining({ include_fallback: 'true', include_branch: 'true', locale: 'fr-fr' })); + return [200, taxonomyFindResponseDataMock.taxonomies[0]]; + }); + + await taxonomy.includeFallback().includeBranch().param('locale', 'fr-fr').fetch(); + }); + + it('should return localized taxonomy when fetch is called with locale', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing').reply(200, taxonomyLocalizedFetchMock); + const response = await taxonomy.fetch('hi-in'); + expect(response).toEqual(taxonomyLocalizedFetchMock.taxonomy); + }); +}); diff --git a/test/unit/term-query.spec.ts b/test/unit/term-query.spec.ts new file mode 100644 index 0000000..e6de3d1 --- /dev/null +++ b/test/unit/term-query.spec.ts @@ -0,0 +1,80 @@ +import { TermQuery } from '../../src/query/term-query'; +import { AxiosInstance, httpClient } from '@contentstack/core'; +import MockAdapter from 'axios-mock-adapter'; +import { termQueryFindResponseDataMock, termQueryLocalizedFindMock } from '../utils/mocks'; +import { MOCK_CLIENT_OPTIONS } from '../utils/constant'; + +describe('TermQuery class', () => { + let termQuery: TermQuery; + let client: AxiosInstance; + let mockClient: MockAdapter; + + beforeAll(() => { + client = httpClient(MOCK_CLIENT_OPTIONS); + mockClient = new MockAdapter(client as any); + }); + + beforeEach(() => { + termQuery = new TermQuery(client, 'taxonomy_testing'); + }); + + it('should return response data when successful', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms').reply(200, termQueryFindResponseDataMock); + const response = await termQuery.find(); + expect(response).toEqual(termQueryFindResponseDataMock); + }); + + it('should send pagination and include params when chained on find()', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms').reply((config) => { + expect(config.params).toEqual(expect.objectContaining({ + depth: 2, + skip: 10, + limit: 5, + include_count: 'true', + include_fallback: 'true', + include_branch: 'true', + })); + return [200, termQueryFindResponseDataMock]; + }); + + await termQuery + .depth(2) + .skip(10) + .limit(5) + .includeCount() + .includeFallback() + .includeBranch() + .find(); + }); + + it('should send arbitrary params added via param() and addParams() on find()', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms').reply((config) => { + expect(config.params).toEqual(expect.objectContaining({ locale: 'fr-fr', order: 1 })); + return [200, termQueryFindResponseDataMock]; + }); + + await termQuery.param('locale', 'fr-fr').addParams({ order: 1 }).find(); + }); + + it('should set locale query param when locale() is called', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms').reply(200, termQueryLocalizedFindMock); + const response = await termQuery.locale('hi-in').find(); + expect(termQuery._queryParams.locale).toBe('hi-in'); + expect(response).toEqual(termQueryLocalizedFindMock); + }); + + it('should set include_fallback query param when includeFallback() is called', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms').reply(200, termQueryFindResponseDataMock); + const response = await termQuery.includeFallback().find(); + expect(termQuery._queryParams.include_fallback).toBe('true'); + expect(response).toEqual(termQueryFindResponseDataMock); + }); + + it('should set both locale and include_fallback when chained', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms').reply(200, termQueryLocalizedFindMock); + const response = await termQuery.locale('hi-in').includeFallback().find(); + expect(termQuery._queryParams.locale).toBe('hi-in'); + expect(termQuery._queryParams.include_fallback).toBe('true'); + expect(response).toEqual(termQueryLocalizedFindMock); + }); +}); diff --git a/test/unit/term.spec.ts b/test/unit/term.spec.ts new file mode 100644 index 0000000..511c444 --- /dev/null +++ b/test/unit/term.spec.ts @@ -0,0 +1,85 @@ +import { AxiosInstance, httpClient } from '@contentstack/core'; +import MockAdapter from 'axios-mock-adapter'; +import { termQueryFindResponseDataMock, termLocalesResponseDataMock, termAncestorsResponseDataMock, termDescendantsResponseDataMock, termLocalizedFetchMock } from '../utils/mocks'; +import { MOCK_CLIENT_OPTIONS } from '../utils/constant'; +import { Term } from '../../src/taxonomy/term'; +import { Taxonomy } from '../../src/taxonomy'; + +describe('Term class', () => { + let term: Term; + let client: AxiosInstance; + let mockClient: MockAdapter; + + beforeAll(() => { + client = httpClient(MOCK_CLIENT_OPTIONS); + mockClient = new MockAdapter(client as any); + }); + + beforeEach(() => { + term = new Term(client, 'taxonomy_testing', 'term1'); + }); + + it('should fetch the term by uid response when fetch method is called', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms/term1').reply(200, termQueryFindResponseDataMock.terms[0]); + + const response = await term.fetch(); + expect(response).toEqual(termQueryFindResponseDataMock.terms[0]); + }); + + it('should fetch locales for a term when locales() is called', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms/term1/locales').reply(200, termLocalesResponseDataMock.terms); + + const response = await term.locales(); + expect(response).toEqual(termLocalesResponseDataMock.terms); + }); + + it('should fetch ancestors for a term when ancestors() is called', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms/term1/ancestors').reply(200, termAncestorsResponseDataMock); + + const response = await term.ancestors(); + expect(response).toEqual(termAncestorsResponseDataMock); + }); + + it('should fetch descendants for a term when descendants() is called', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms/term1/descendants').reply(200, termDescendantsResponseDataMock); + + const response = await term.descendants(); + expect(response).toEqual(termDescendantsResponseDataMock); + }); + + it('should send depth param on descendants() when depth() is chained', async () => { + mockClient + .onGet('/taxonomies/taxonomy_testing/terms/term1/descendants') + .reply((config) => { + expect(config.params).toEqual(expect.objectContaining({ depth: 2 })); + return [200, termDescendantsResponseDataMock]; + }); + + await term.depth(2).descendants(); + }); + + it('should send include_fallback and include_branch params on fetch()', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms/term1').reply((config) => { + expect(config.params).toEqual(expect.objectContaining({ include_fallback: 'true', include_branch: 'true' })); + return [200, termQueryFindResponseDataMock.terms[0]]; + }); + + await term.includeFallback().includeBranch().fetch(); + }); + + it('should send arbitrary params added via param() and addParams() on ancestors()', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms/term1/ancestors').reply((config) => { + expect(config.params).toEqual(expect.objectContaining({ depth: 1, locale: 'fr-fr' })); + return [200, termAncestorsResponseDataMock]; + }); + + await term.param('depth', 1).addParams({ locale: 'fr-fr' }).ancestors(); + }); + + it('should fetch localized term when fetch is called with locale', async () => { + mockClient.onGet('/taxonomies/taxonomy_testing/terms/term1').reply(200, termLocalizedFetchMock); + + const response = await term.fetch('hi-in'); + expect(response).toEqual(termLocalizedFetchMock.term); + }); +}); diff --git a/test/utils/mocks.ts b/test/utils/mocks.ts index a265d0c..38c94d3 100644 --- a/test/utils/mocks.ts +++ b/test/utils/mocks.ts @@ -1676,6 +1676,250 @@ const gfieldQueryFindResponseDataMock = { ] } +const taxonomyFindResponseDataMock = { + "taxonomies": [ + { + "uid": "taxonomy_testing", + "name": "taxonomy testing", + "description": "", + "terms_count": 1, + "created_at": "2025-10-10T06:42:48.644Z", + "updated_at": "2025-10-10T06:42:48.644Z", + "created_by": "created_by", + "updated_by": "updated_by", + "type": "TAXONOMY", + "ACL": {}, + "publish_details": { + "time": "2025-10-10T08:01:48.174Z", + "user": "user", + "environment": "env", + "locale": "en-us" + } + } + ] +} + +const termLocalesResponseDataMock = { + terms: [] +} + +const termAncestorsResponseDataMock = { + "terms": [ + { + "uid": "vehicles", + "name": "vehicles", + "publish_details": { + "time": "2025-10-28T06:54:12.505Z", + "user": "user", + "environment": "environment", + "locale": "en-us" + } + }, + { + "uid": "buses", + "name": "buses", + "publish_details": { + "time": "2025-10-28T06:54:12.514Z", + "user": "user", + "environment": "environment", + "locale": "en-us" + } + }, + { + "uid": "vrl", + "name": "vrl", + "publish_details": { + "time": "2025-10-28T06:54:12.570Z", + "user": "user", + "environment": "environment", + "locale": "en-us" + } + } + ] +} + +const termDescendantsResponseDataMock = { + "terms": [ + { + "taxonomy_uid": "taxonomy_testing", + "uid": "sleeper", + "ancestors": [ + { + "uid": "taxonomy_testing", + "name": "taxonomy_testing", + "type": "TAXONOMY" + }, + { + "uid": "vehicles", + "name": "vehicles", + "type": "" + }, + { + "uid": "buses", + "name": "buses", + "type": "" + }, + { + "uid": "vrl", + "name": "vrl", + "type": "" + } + ], + "name": "sleeper", + "parent_uid": "vrl", + "created_by": "created_by", + "created_at": "2025-10-28T07:58:46.870Z", + "updated_by": "updated_by", + "updated_at": "2025-10-28T07:58:46.870Z", + "children_count": 0, + "depth": 4, + "ACL": {}, + "publish_details": { + "time": "2025-10-28T07:59:12.557Z", + "user": "user", + "environment": "environment", + "locale": "en-us" + } + }, + { + "taxonomy_uid": "taxonomy_testing", + "uid": "intercity", + "ancestors": [ + { + "uid": "taxonomy_testing", + "name": "taxonomy_testing", + "type": "TAXONOMY" + }, + { + "uid": "vehicles", + "name": "vehicles", + "type": "" + }, + { + "uid": "buses", + "name": "buses", + "type": "" + }, + { + "uid": "vrl", + "name": "vrl", + "type": "" + } + ], + "name": "intercity", + "parent_uid": "vrl", + "created_by": "created_by", + "created_at": "2025-10-28T07:58:46.870Z", + "updated_by": "updated_by", + "updated_at": "2025-10-28T07:58:46.870Z", + "children_count": 0, + "depth": 4, + "ACL": {}, + "publish_details": { + "time": "2025-10-28T07:59:12.565Z", + "user": "user", + "environment": "environment", + "locale": "en-us" + } + } + ] +} + +const termQueryFindResponseDataMock = { + "terms": [ + { + "taxonomy_uid": "taxonomy_testing", + "uid": "term1", + "ancestors": [ + { + "uid": "taxonomy_testing", + "name": "taxonomy testing", + "type": "TAXONOMY" + } + ], + "name": "term1", + "created_by": "created_by", + "created_at": "2025-10-10T06:43:13.799Z", + "updated_by": "updated_by", + "updated_at": "2025-10-10T06:43:13.799Z", + "children_count": 0, + "depth": 1, + "ACL": {}, + "publish_details": { + "time": "2025-10-10T08:01:48.351Z", + "user": "user", + "environment": "environment", + "locale": "en-us" + } + } +] +} + +const taxonomyLocalizedFetchMock = { + "taxonomy": { + "uid": "taxonomy_testing", + "locale": "hi-in", + "name": "टैक्सोनॉमी परीक्षण", + "description": "", + "created_at": "2025-10-10T06:42:48.644Z", + "updated_at": "2025-10-10T06:42:48.644Z", + "created_by": "created_by", + "updated_by": "updated_by", + "publish_details": { + "time": "2025-10-10T08:01:48.174Z", + "user": "user", + "environment": "env", + "locale": "hi-in" + } + } +}; + +const termLocalizedFetchMock = { + "term": { + "taxonomy_uid": "taxonomy_testing", + "uid": "term1", + "locale": "hi-in", + "name": "टर्म एक", + "ancestors": [{ "uid": "taxonomy_testing", "name": "taxonomy testing", "type": "TAXONOMY" }], + "depth": 1, + "parent_uid": null, + "created_by": "created_by", + "created_at": "2025-10-10T06:43:13.799Z", + "updated_by": "updated_by", + "updated_at": "2025-10-10T06:43:13.799Z", + "publish_details": { + "time": "2025-10-10T08:01:48.351Z", + "user": "user", + "environment": "environment", + "locale": "hi-in" + } + } +}; + +const termQueryLocalizedFindMock = { + "terms": [ + { + "taxonomy_uid": "taxonomy_testing", + "uid": "term1", + "locale": "hi-in", + "name": "टर्म एक", + "ancestors": [{ "uid": "taxonomy_testing", "name": "taxonomy testing", "type": "TAXONOMY" }], + "depth": 1, + "parent_uid": null, + "created_by": "created_by", + "created_at": "2025-10-10T06:43:13.799Z", + "updated_by": "updated_by", + "updated_at": "2025-10-10T06:43:13.799Z", + "publish_details": { + "time": "2025-10-10T08:01:48.351Z", + "user": "user", + "environment": "environment", + "locale": "hi-in" + } + } + ] +}; + const syncResult: any = { ...axiosGetMock.data }; export { @@ -1688,5 +1932,13 @@ export { entryFindMock, entryFetchMock, gfieldFetchDataMock, - gfieldQueryFindResponseDataMock + gfieldQueryFindResponseDataMock, + taxonomyFindResponseDataMock, + termQueryFindResponseDataMock, + termLocalesResponseDataMock, + termAncestorsResponseDataMock, + termDescendantsResponseDataMock, + taxonomyLocalizedFetchMock, + termLocalizedFetchMock, + termQueryLocalizedFindMock, };