Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/lib/taxonomy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { AxiosInstance, getData } from '@contentstack/core';
import { TermQuery } from './term-query';
import { Term } from './term';

export class Taxonomy {
private _client: AxiosInstance;
Expand All @@ -13,6 +15,14 @@ export class Taxonomy {
this._urlPath = `/taxonomy-manager/${this._taxonomyUid}`; // TODO: change to /taxonomies/${this._taxonomyUid}
}

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);
}

async fetch<T>(): Promise<T> {
const response = await getData(this._client, this._urlPath);

Expand Down
20 changes: 20 additions & 0 deletions src/lib/term-query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { AxiosInstance, getData } from '@contentstack/core';
import { FindResponse } from './types';

export class TermQuery {
private _taxonomyUid: string;
private _client: AxiosInstance;
private _urlPath: string;
_queryParams: { [key: string]: string | number } = {};

constructor(client: AxiosInstance, taxonomyUid: string) {
this._client = client;
this._taxonomyUid = taxonomyUid;
this._urlPath = `/taxonomy-manager/${this._taxonomyUid}/terms`;
}

async find<T>(): Promise<FindResponse<T>> {
const response = await getData(this._client, this._urlPath, { params: this._queryParams });
return response as FindResponse<T>;
}
}
22 changes: 22 additions & 0 deletions src/lib/term.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { AxiosInstance, getData } from "@contentstack/core";

export class Term {
protected _client: AxiosInstance;
private _taxonomyUid: string;
private _termUid: string;
private _urlPath: string;

constructor(client: AxiosInstance, taxonomyUid: string, termUid: string) {
this._client = client;
this._taxonomyUid = taxonomyUid;
this._termUid = termUid;
this._urlPath = `/taxonomy-manager/${this._taxonomyUid}/terms/${this._termUid}`; // TODO: change to /taxonomies
}
async fetch<T>(): Promise<T> {
const response = await getData(this._client, this._urlPath);

if (response.term) return response.term as T;

return response;
}
}
2 changes: 2 additions & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ export interface FindResponse<T> {
assets?: T[];
global_fields?: T[];
count?: number;
taxonomies?: T[];
terms?: T[];
}

export interface LivePreviewQuery {
Expand Down
23 changes: 23 additions & 0 deletions test/api/term-query.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { TermQuery } from "../../src/lib/term-query";
import { stackInstance } from "../utils/stack-instance";
import { TTerm } from "./types";

const stack = stackInstance();

describe("Terms API test cases", () => {
it("should check for terms is defined", async () => {
const result = await makeTerms("taxonomy_testing").find<TTerm>();
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();
}
});
});
function makeTerms(taxonomyUid = ""): TermQuery {
const terms = stack.taxonomy(taxonomyUid).term();

return terms;
}
20 changes: 20 additions & 0 deletions test/api/term.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Term } from "../../src/lib/term";
import { stackInstance } from "../utils/stack-instance";
import { TTerm } from "./types";

const stack = stackInstance();

describe("Terms API test cases", () => {
it("should get a term by uid", async () => {
const result = await makeTerms("term1").fetch<TTerm>();
expect(result).toBeDefined();
expect(result.taxonomy_uid).toBeDefined();
expect(result.uid).toBeDefined();
expect(result.created_by).toBeDefined();
expect(result.updated_by).toBeDefined();
});
});
function makeTerms(termUid = ""): Term {
const terms = stack.taxonomy("taxonomy_testing").term(termUid);
return terms;
}
22 changes: 20 additions & 2 deletions test/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,29 @@ export interface TTaxonomy {
uid: string;
name: string;
description?: string;
terms_count: number;
terms_count?: number;
created_at: string;
updated_at: string;
created_by: string;
updated_by: string;
type: string;
publish_details: PublishDetails;
publish_details?: PublishDetails;
}

export interface TTerms {
terms: TTerm[];
}

export interface TTerm {
taxonomy_uid: string;
uid: string;
ancestors: TTerm[];
name: string;
created_by: string;
created_at: string;
updated_by: string;
updated_at: string;
children_count?: number;
depth?: number;
publish_details?: PublishDetails;
}
14 changes: 13 additions & 1 deletion test/unit/taxonomy.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { AxiosInstance, httpClient } from '@contentstack/core';
import MockAdapter from 'axios-mock-adapter';
import { taxonomyFindResponseDataMock } from '../utils/mocks';
import { MOCK_CLIENT_OPTIONS } from '../utils/constant';
import { Term } from '../../src/lib/term';
import { TermQuery } from '../../src/lib/term-query';

describe('ta class', () => {
let taxonomies: TaxonomyQuery;
Expand All @@ -21,6 +23,16 @@ describe('ta class', () => {
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('/taxonomy-manager').reply(200, taxonomyFindResponseDataMock); //TODO: change to /taxonomies
const response = await taxonomies.find();
Expand All @@ -30,6 +42,6 @@ describe('ta class', () => {
it('should return single taxonomy in the response data when successful', async () => {
mockClient.onGet('/taxonomy-manager/taxonomy_testing').reply(200, taxonomyFindResponseDataMock.taxonomies[0]); //TODO: change to /taxonomies/taxonomyUid
const response = await taxonomy.fetch();
expect(response).toEqual(taxonomyFindResponseDataMock.taxonomies[0]); //TODO: change to taxonomyFindResponseDataMock
expect(response).toEqual(taxonomyFindResponseDataMock.taxonomies[0]);
});
});
26 changes: 26 additions & 0 deletions test/unit/term-query.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { TermQuery } from '../../src/lib/term-query';
import { AxiosInstance, httpClient } from '@contentstack/core';
import MockAdapter from 'axios-mock-adapter';
import { termQueryFindResponseDataMock } 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('/taxonomy-manager/taxonomy_testing/terms').reply(200, termQueryFindResponseDataMock);
const response = await termQuery.find();
expect(response).toEqual(termQueryFindResponseDataMock);
});
});
28 changes: 28 additions & 0 deletions test/unit/term.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { AxiosInstance, httpClient } from '@contentstack/core';
import MockAdapter from 'axios-mock-adapter';
import { termQueryFindResponseDataMock } from '../utils/mocks';
import { MOCK_CLIENT_OPTIONS } from '../utils/constant';
import { Term } from '../../src/lib/term';
import { Taxonomy } from '../../src/lib/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('/taxonomy-manager/taxonomy_testing/terms/term1').reply(200, termQueryFindResponseDataMock.terms[0]); //TODO: change to /taxonomies

const response = await term.fetch();
expect(response).toEqual(termQueryFindResponseDataMock.terms[0]);
});
});
32 changes: 31 additions & 1 deletion test/utils/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,35 @@ const taxonomyFindResponseDataMock = {
}
]
}
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 syncResult: any = { ...axiosGetMock.data };

Expand All @@ -1712,5 +1741,6 @@ export {
entryFetchMock,
gfieldFetchDataMock,
gfieldQueryFindResponseDataMock,
taxonomyFindResponseDataMock
taxonomyFindResponseDataMock,
termQueryFindResponseDataMock,
};