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
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { SourceFiles } from './sourceFiles';
import { SourceStrings } from './sourceStrings';
import { StringComments } from './stringComments';
import { StringCorrections } from './stringCorrections';
import { StyleGuides } from './styleGuides';
import { StringTranslations } from './stringTranslations';
import { Tasks } from './tasks';
import { Teams } from './teams';
Expand Down Expand Up @@ -56,6 +57,7 @@ export * from './sourceFiles';
export * from './sourceStrings';
export * from './stringComments';
export * from './stringCorrections';
export * from './styleGuides';
export * from './stringTranslations';
export * from './tasks';
export * from './teams';
Expand Down Expand Up @@ -108,6 +110,7 @@ export default class Client extends CrowdinApi {
readonly securityLogsApi: SecurityLogs;
readonly fieldsApi: Fields;
readonly stringCorrectionsApi: StringCorrections;
readonly styleGuidesApi: StyleGuides;

constructor(credentials: Credentials, config?: ClientConfig) {
super(credentials, config);
Expand Down Expand Up @@ -144,6 +147,7 @@ export default class Client extends CrowdinApi {
this.securityLogsApi = new SecurityLogs(credentials, config);
this.fieldsApi = new Fields(credentials, config);
this.stringCorrectionsApi = new StringCorrections(credentials, config);
this.styleGuidesApi = new StyleGuides(credentials, config);
}
}

Expand Down
88 changes: 88 additions & 0 deletions src/styleGuides/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { CrowdinApi, PaginationOptions, PatchRequest, ResponseList, ResponseObject } from '../core';

export class StyleGuides extends CrowdinApi {
/**
* @param options optional parameters for the request
* @see https://developer.crowdin.com/api/v2/#operation/api.style-guides.getMany
*/
listStyleGuides(
options?: StyleGuidesModel.ListStyleGuidesOptions,
): Promise<ResponseList<StyleGuidesModel.StyleGuide>> {
let url = `${this.url}/style-guides`;
url = this.addQueryParam(url, 'orderBy', options?.orderBy);
url = this.addQueryParam(url, 'userId', options?.userId);
return this.getList(url, options?.limit, options?.offset);
}

/**
* @param request request body
* @see https://developer.crowdin.com/api/v2/#operation/api.style-guides.post
*/
createStyleGuide(
request: StyleGuidesModel.CreateStyleGuideRequest,
): Promise<ResponseObject<StyleGuidesModel.StyleGuide>> {
const url = `${this.url}/style-guides`;
return this.post(url, request, this.defaultConfig());
}

/**
* @param styleGuideId style guide identifier
* @see https://developer.crowdin.com/api/v2/#operation/api.style-guides.get
*/
getStyleGuide(styleGuideId: number): Promise<ResponseObject<StyleGuidesModel.StyleGuide>> {
const url = `${this.url}/style-guides/${styleGuideId}`;
return this.get(url, this.defaultConfig());
}

/**
* @param styleGuideId style guide identifier
* @see https://developer.crowdin.com/api/v2/#operation/api.style-guides.delete
*/
deleteStyleGuide(styleGuideId: number): Promise<void> {
const url = `${this.url}/style-guides/${styleGuideId}`;
return this.delete(url, this.defaultConfig());
}

/**
* @param styleGuideId style guide identifier
* @param request request body
* @see https://developer.crowdin.com/api/v2/#operation/api.style-guides.patch
*/
editStyleGuide(
styleGuideId: number,
request: PatchRequest[],
): Promise<ResponseObject<StyleGuidesModel.StyleGuide>> {
const url = `${this.url}/style-guides/${styleGuideId}`;
return this.patch(url, request, this.defaultConfig());
}
}

export namespace StyleGuidesModel {
export interface StyleGuide {
id: number;
name: string;
aiInstructions: string | null;
userId: number;
languageIds: string[] | null;
projectIds: number[] | null;
isShared: boolean;
webUrl: string;
downloadLink: string;
createdAt: string;
updatedAt: string;
}

export interface CreateStyleGuideRequest {
name: string;
storageId: number | null;
aiInstructions?: string;
languageIds?: string[];
projectIds?: number[];
isShared?: boolean;
}

export interface ListStyleGuidesOptions extends PaginationOptions {
orderBy?: string;
userId?: number;
}
}
127 changes: 127 additions & 0 deletions tests/styleGuides/api.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import * as nock from 'nock';
import { Credentials, StyleGuides } from '../../src';

describe('Style Guides API', () => {
let scope: nock.Scope;
const credentials: Credentials = {
token: 'testToken',
organization: 'testOrg',
};
const api: StyleGuides = new StyleGuides(credentials);
const styleGuideId = 2;
const storageId = 1;
const name = "Be My Eyes iOS's Style Guide";

const limit = 25;

beforeAll(() => {
scope = nock(api.url)
.get('/style-guides', undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
})
.reply(200, {
data: [
{
data: {
id: styleGuideId,
},
},
],
pagination: {
offset: 0,
limit: limit,
},
})
.post(
'/style-guides',
{
name,
storageId,
},
{
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
},
)
.reply(200, {
data: {
id: styleGuideId,
},
})
.get(`/style-guides/${styleGuideId}`, undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
})
.reply(200, {
data: {
id: styleGuideId,
},
})
.delete(`/style-guides/${styleGuideId}`, undefined, {
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
})
.reply(200)
.patch(
`/style-guides/${styleGuideId}`,
[
{
op: 'replace',
path: '/name',
value: name,
},
],
{
reqheaders: {
Authorization: `Bearer ${api.token}`,
},
},
)
.reply(200, {
data: {
id: styleGuideId,
},
});
});

afterAll(() => {
scope.done();
});

it('List style guides', async () => {
const styleGuides = await api.listStyleGuides();
expect(styleGuides.data.length).toBe(1);
expect(styleGuides.data[0].data.id).toBe(styleGuideId);
expect(styleGuides.pagination.limit).toBe(limit);
});

it('Create style guide', async () => {
const styleGuide = await api.createStyleGuide({ name, storageId });
expect(styleGuide.data.id).toBe(styleGuideId);
});

it('Get style guide', async () => {
const styleGuide = await api.getStyleGuide(styleGuideId);
expect(styleGuide.data.id).toBe(styleGuideId);
});

it('Delete style guide', async () => {
await api.deleteStyleGuide(styleGuideId);
});

it('Edit style guide', async () => {
const styleGuide = await api.editStyleGuide(styleGuideId, [
{
op: 'replace',
path: '/name',
value: name,
},
]);
expect(styleGuide.data.id).toBe(styleGuideId);
});
});
Loading