smartling-api-sdk-nodejs 3.4.2 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -1
- package/api/estimates/dto/effective-rates-range-dto.ts +7 -0
- package/api/estimates/dto/estimate-report-dto.ts +34 -0
- package/api/estimates/dto/estimate-report-status-dto.ts +13 -0
- package/api/estimates/dto/estimate-report-tags-dto.ts +5 -0
- package/api/estimates/dto/fuzzy-match-tier-dto.ts +17 -0
- package/api/estimates/dto/generated-estimate-report-dto.ts +10 -0
- package/api/estimates/dto/locale-estimate-dto.ts +17 -0
- package/api/estimates/dto/locale-workflow-pair-dto.ts +6 -0
- package/api/estimates/dto/locale-workflow-step-pair-dto.ts +6 -0
- package/api/estimates/dto/price-information-dto.ts +12 -0
- package/api/estimates/dto/workflow-estimate-dto.ts +18 -0
- package/api/estimates/dto/workflow-step-estimate-dto.ts +21 -0
- package/api/estimates/index.ts +102 -0
- package/api/estimates/params/estimate-report-content-coverage.ts +4 -0
- package/api/estimates/params/estimate-report-status.ts +9 -0
- package/api/estimates/params/estimate-report-type.ts +4 -0
- package/api/estimates/params/fuzzy-match-type-code.ts +4 -0
- package/api/estimates/params/generate-job-estimate-report-parameters.ts +46 -0
- package/api/estimates/params/job-content-type.ts +6 -0
- package/api/estimates/params/list-job-estimate-reports-parameters.ts +64 -0
- package/api/estimates/params/modify-estimate-report-tags-parameters.ts +9 -0
- package/api/translation-memory/index.ts +39 -0
- package/api/translation-memory/params/search-tms-parameters.ts +47 -0
- package/api/translation-memory/params/tm-sorting.ts +4 -0
- package/built/api/estimates/dto/effective-rates-range-dto.d.ts +6 -0
- package/built/api/estimates/dto/effective-rates-range-dto.js +3 -0
- package/built/api/estimates/dto/effective-rates-range-dto.js.map +1 -0
- package/built/api/estimates/dto/estimate-report-dto.d.ts +30 -0
- package/built/api/estimates/dto/estimate-report-dto.js +3 -0
- package/built/api/estimates/dto/estimate-report-dto.js.map +1 -0
- package/built/api/estimates/dto/estimate-report-status-dto.d.ts +11 -0
- package/built/api/estimates/dto/estimate-report-status-dto.js +3 -0
- package/built/api/estimates/dto/estimate-report-status-dto.js.map +1 -0
- package/built/api/estimates/dto/estimate-report-tags-dto.d.ts +4 -0
- package/built/api/estimates/dto/estimate-report-tags-dto.js +3 -0
- package/built/api/estimates/dto/estimate-report-tags-dto.js.map +1 -0
- package/built/api/estimates/dto/fuzzy-match-tier-dto.d.ts +12 -0
- package/built/api/estimates/dto/fuzzy-match-tier-dto.js +3 -0
- package/built/api/estimates/dto/fuzzy-match-tier-dto.js.map +1 -0
- package/built/api/estimates/dto/generated-estimate-report-dto.d.ts +8 -0
- package/built/api/estimates/dto/generated-estimate-report-dto.js +3 -0
- package/built/api/estimates/dto/generated-estimate-report-dto.js.map +1 -0
- package/built/api/estimates/dto/locale-estimate-dto.d.ts +13 -0
- package/built/api/estimates/dto/locale-estimate-dto.js +3 -0
- package/built/api/estimates/dto/locale-estimate-dto.js.map +1 -0
- package/built/api/estimates/dto/locale-workflow-pair-dto.d.ts +5 -0
- package/built/api/estimates/dto/locale-workflow-pair-dto.js +3 -0
- package/built/api/estimates/dto/locale-workflow-pair-dto.js.map +1 -0
- package/built/api/estimates/dto/locale-workflow-step-pair-dto.d.ts +5 -0
- package/built/api/estimates/dto/locale-workflow-step-pair-dto.js +3 -0
- package/built/api/estimates/dto/locale-workflow-step-pair-dto.js.map +1 -0
- package/built/api/estimates/dto/price-information-dto.d.ts +9 -0
- package/built/api/estimates/dto/price-information-dto.js +3 -0
- package/built/api/estimates/dto/price-information-dto.js.map +1 -0
- package/built/api/estimates/dto/workflow-estimate-dto.d.ts +13 -0
- package/built/api/estimates/dto/workflow-estimate-dto.js +3 -0
- package/built/api/estimates/dto/workflow-estimate-dto.js.map +1 -0
- package/built/api/estimates/dto/workflow-step-estimate-dto.d.ts +17 -0
- package/built/api/estimates/dto/workflow-step-estimate-dto.js +3 -0
- package/built/api/estimates/dto/workflow-step-estimate-dto.js.map +1 -0
- package/built/api/estimates/index.d.ts +23 -0
- package/built/api/estimates/index.js +68 -0
- package/built/api/estimates/index.js.map +1 -0
- package/built/api/estimates/params/estimate-report-content-coverage.d.ts +4 -0
- package/built/api/estimates/params/estimate-report-content-coverage.js +9 -0
- package/built/api/estimates/params/estimate-report-content-coverage.js.map +1 -0
- package/built/api/estimates/params/estimate-report-status.d.ts +9 -0
- package/built/api/estimates/params/estimate-report-status.js +14 -0
- package/built/api/estimates/params/estimate-report-status.js.map +1 -0
- package/built/api/estimates/params/estimate-report-type.d.ts +4 -0
- package/built/api/estimates/params/estimate-report-type.js +9 -0
- package/built/api/estimates/params/estimate-report-type.js.map +1 -0
- package/built/api/estimates/params/fuzzy-match-type-code.d.ts +4 -0
- package/built/api/estimates/params/fuzzy-match-type-code.js +9 -0
- package/built/api/estimates/params/fuzzy-match-type-code.js.map +1 -0
- package/built/api/estimates/params/generate-job-estimate-report-parameters.d.ts +12 -0
- package/built/api/estimates/params/generate-job-estimate-report-parameters.js +32 -0
- package/built/api/estimates/params/generate-job-estimate-report-parameters.js.map +1 -0
- package/built/api/estimates/params/job-content-type.d.ts +6 -0
- package/built/api/estimates/params/job-content-type.js +11 -0
- package/built/api/estimates/params/job-content-type.js.map +1 -0
- package/built/api/estimates/params/list-job-estimate-reports-parameters.d.ts +15 -0
- package/built/api/estimates/params/list-job-estimate-reports-parameters.js +44 -0
- package/built/api/estimates/params/list-job-estimate-reports-parameters.js.map +1 -0
- package/built/api/estimates/params/modify-estimate-report-tags-parameters.d.ts +4 -0
- package/built/api/estimates/params/modify-estimate-report-tags-parameters.js +12 -0
- package/built/api/estimates/params/modify-estimate-report-tags-parameters.js.map +1 -0
- package/built/api/translation-memory/index.d.ts +3 -0
- package/built/api/translation-memory/index.js +24 -0
- package/built/api/translation-memory/index.js.map +1 -1
- package/built/api/translation-memory/params/search-tms-parameters.d.ts +12 -0
- package/built/api/translation-memory/params/search-tms-parameters.js +36 -0
- package/built/api/translation-memory/params/search-tms-parameters.js.map +1 -0
- package/built/api/translation-memory/params/tm-sorting.d.ts +4 -0
- package/built/api/translation-memory/params/tm-sorting.js +9 -0
- package/built/api/translation-memory/params/tm-sorting.js.map +1 -0
- package/built/index.d.ts +23 -0
- package/built/index.js +23 -0
- package/built/index.js.map +1 -1
- package/built/package.json +1 -1
- package/built/test/estimates.spec.d.ts +1 -0
- package/built/test/estimates.spec.js +191 -0
- package/built/test/estimates.spec.js.map +1 -0
- package/built/test/integration/estimates.spec.d.ts +1 -0
- package/built/test/integration/estimates.spec.js +182 -0
- package/built/test/integration/estimates.spec.js.map +1 -0
- package/built/test/integration/helpers/log-response.js +1 -2
- package/built/test/integration/helpers/log-response.js.map +1 -1
- package/built/test/integration/translation-memory.spec.js +32 -1
- package/built/test/integration/translation-memory.spec.js.map +1 -1
- package/built/test/translation-memory.spec.js +60 -0
- package/built/test/translation-memory.spec.js.map +1 -1
- package/index.ts +23 -0
- package/package.json +1 -1
- package/test/estimates.spec.ts +242 -0
- package/test/integration/estimates.spec.ts +271 -0
- package/test/integration/helpers/log-response.ts +5 -3
- package/test/integration/translation-memory.spec.ts +52 -1
- package/test/translation-memory.spec.ts +79 -1
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import dotenv from "dotenv";
|
|
2
|
+
import assert from "assert";
|
|
3
|
+
import { SmartlingApiClientBuilder } from "../../api/builder/index";
|
|
4
|
+
import { SmartlingEstimatesApi } from "../../api/estimates/index";
|
|
5
|
+
import { SmartlingJobsApi } from "../../api/jobs/index";
|
|
6
|
+
import { SmartlingProjectsApi } from "../../api/projects/index";
|
|
7
|
+
import { SmartlingFilesApi } from "../../api/files/index";
|
|
8
|
+
import { CreateJobParameters } from "../../api/jobs/params/create-job-parameters";
|
|
9
|
+
import { CancelJobParameters } from "../../api/jobs/params/cancel-job-parameters";
|
|
10
|
+
import { AddFileParameters } from "../../api/jobs/params/add-file-parameters";
|
|
11
|
+
import { AuthorizeJobParameters } from "../../api/jobs/params/authorize-job-parameters";
|
|
12
|
+
import { UploadFileParameters } from "../../api/files/params/upload-file-parameters";
|
|
13
|
+
import { FileType } from "../../api/files/params/file-type";
|
|
14
|
+
import { GenerateJobEstimateReportParameters } from "../../api/estimates/params/generate-job-estimate-report-parameters";
|
|
15
|
+
import { ListJobEstimateReportsParameters } from "../../api/estimates/params/list-job-estimate-reports-parameters";
|
|
16
|
+
import { ModifyEstimateReportTagsParameters } from "../../api/estimates/params/modify-estimate-report-tags-parameters";
|
|
17
|
+
import { JobContentType } from "../../api/estimates/params/job-content-type";
|
|
18
|
+
import { EstimateReportStatus } from "../../api/estimates/params/estimate-report-status";
|
|
19
|
+
import { logResponse } from "./helpers/log-response";
|
|
20
|
+
|
|
21
|
+
dotenv.config();
|
|
22
|
+
|
|
23
|
+
const baseSmartlingApiUrl = process.env.SMARTLING_API_BASE_URL || "https://api.smartling.com";
|
|
24
|
+
const accountUid = process.env.SMARTLING_ACCOUNT_UID as string;
|
|
25
|
+
const userId = process.env.SMARTLING_USER_ID as string;
|
|
26
|
+
const userSecret = process.env.SMARTLING_USER_SECRET as string;
|
|
27
|
+
const hasCredentials = Boolean(accountUid && userId && userSecret);
|
|
28
|
+
|
|
29
|
+
const TERMINAL_REPORT_STATUSES = [
|
|
30
|
+
EstimateReportStatus.COMPLETED,
|
|
31
|
+
EstimateReportStatus.FAILED,
|
|
32
|
+
EstimateReportStatus.TIMEOUT,
|
|
33
|
+
EstimateReportStatus.CANCELED,
|
|
34
|
+
EstimateReportStatus.NOT_FOUND
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
function delay(milliseconds: number): Promise<void> {
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
setTimeout(resolve, milliseconds);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
describe("SmartlingEstimatesApi integration tests.", function integrationSuite() {
|
|
44
|
+
this.timeout(180000);
|
|
45
|
+
|
|
46
|
+
let estimatesApi: SmartlingEstimatesApi;
|
|
47
|
+
let jobsApi: SmartlingJobsApi;
|
|
48
|
+
let projectsApi: SmartlingProjectsApi;
|
|
49
|
+
let filesApi: SmartlingFilesApi;
|
|
50
|
+
let projectId: string;
|
|
51
|
+
let translationJobUid: string;
|
|
52
|
+
let fileUri: string;
|
|
53
|
+
let fuzzyReportUid: string | undefined;
|
|
54
|
+
let costReportUid: string | undefined;
|
|
55
|
+
|
|
56
|
+
before(function skipWithoutCredentials() {
|
|
57
|
+
if (!hasCredentials) {
|
|
58
|
+
// eslint-disable-next-line no-console
|
|
59
|
+
console.log("Skipping Estimates integration tests: set SMARTLING_ACCOUNT_UID, SMARTLING_USER_ID, SMARTLING_USER_SECRET in .env");
|
|
60
|
+
this.skip();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
estimatesApi = new SmartlingApiClientBuilder()
|
|
64
|
+
.setBaseSmartlingApiUrl(baseSmartlingApiUrl)
|
|
65
|
+
.authWithUserIdAndUserSecret(userId, userSecret)
|
|
66
|
+
.build(SmartlingEstimatesApi);
|
|
67
|
+
|
|
68
|
+
jobsApi = new SmartlingApiClientBuilder()
|
|
69
|
+
.setBaseSmartlingApiUrl(baseSmartlingApiUrl)
|
|
70
|
+
.authWithUserIdAndUserSecret(userId, userSecret)
|
|
71
|
+
.build(SmartlingJobsApi);
|
|
72
|
+
|
|
73
|
+
projectsApi = new SmartlingApiClientBuilder()
|
|
74
|
+
.setBaseSmartlingApiUrl(baseSmartlingApiUrl)
|
|
75
|
+
.authWithUserIdAndUserSecret(userId, userSecret)
|
|
76
|
+
.build(SmartlingProjectsApi);
|
|
77
|
+
|
|
78
|
+
filesApi = new SmartlingApiClientBuilder()
|
|
79
|
+
.setBaseSmartlingApiUrl(baseSmartlingApiUrl)
|
|
80
|
+
.authWithUserIdAndUserSecret(userId, userSecret)
|
|
81
|
+
.build(SmartlingFilesApi);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
before(async () => {
|
|
85
|
+
const projects = await projectsApi.listProjects(accountUid);
|
|
86
|
+
|
|
87
|
+
logResponse("listProjects", projects);
|
|
88
|
+
assert.ok(projects.items.length > 0, "Test account must have at least one project to run Estimates integration tests");
|
|
89
|
+
|
|
90
|
+
({ projectId } = projects.items[0]);
|
|
91
|
+
|
|
92
|
+
const project = await projectsApi.getProjectDetails(projectId);
|
|
93
|
+
|
|
94
|
+
logResponse("getProjectDetails", project);
|
|
95
|
+
|
|
96
|
+
const targetLocaleIds = project.targetLocales.map((locale) => locale.localeId);
|
|
97
|
+
|
|
98
|
+
const job = await jobsApi.createJob(
|
|
99
|
+
projectId,
|
|
100
|
+
new CreateJobParameters()
|
|
101
|
+
.setName(`api-sdk-nodejs estimates integration test ${Date.now()}`)
|
|
102
|
+
.setTargetLocaleIds(targetLocaleIds)
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
logResponse("createJob", job);
|
|
106
|
+
({ translationJobUid } = job);
|
|
107
|
+
|
|
108
|
+
// Real translatable content, so the generated reports have non-zero word counts and
|
|
109
|
+
// a populated locale/workflow/fuzzy-match breakdown to verify the nested DTOs against.
|
|
110
|
+
fileUri = `api-sdk-nodejs-estimates-integration-test-${Date.now()}.json`;
|
|
111
|
+
|
|
112
|
+
const uploaded = await filesApi.uploadFile(
|
|
113
|
+
projectId,
|
|
114
|
+
new UploadFileParameters()
|
|
115
|
+
.setFileUri(fileUri)
|
|
116
|
+
.setFileType(FileType.JSON)
|
|
117
|
+
.setFileContent(JSON.stringify({
|
|
118
|
+
greeting: "Hello, welcome to our service!",
|
|
119
|
+
farewell: "Thank you for using our application, we hope to see you again soon.",
|
|
120
|
+
description: "This is a sample piece of content used to generate a translation estimate for integration testing purposes."
|
|
121
|
+
}))
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
logResponse("uploadFile", uploaded);
|
|
125
|
+
|
|
126
|
+
const addedFile = await jobsApi.addFileToJob(
|
|
127
|
+
projectId,
|
|
128
|
+
translationJobUid,
|
|
129
|
+
new AddFileParameters().setFileUri(fileUri).setTargetLocaleIds(targetLocaleIds)
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
logResponse("addFileToJob", addedFile);
|
|
133
|
+
|
|
134
|
+
// Assigns the project's default workflow per locale, so the estimate has a workflow
|
|
135
|
+
// to break the word counts down by.
|
|
136
|
+
const authorized = await jobsApi.authorizeJob(
|
|
137
|
+
projectId, translationJobUid, new AuthorizeJobParameters()
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
logResponse("authorizeJob", authorized);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
after(async () => {
|
|
144
|
+
// Guards against a leaked report if an assertion in the `it` block below threw before
|
|
145
|
+
// reaching that test's own deleteEstimateReport call - each test clears its tracked uid
|
|
146
|
+
// once it deletes the report itself, so this is a no-op on the happy path.
|
|
147
|
+
if (fuzzyReportUid) {
|
|
148
|
+
await estimatesApi.deleteEstimateReport(projectId, fuzzyReportUid);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (costReportUid) {
|
|
152
|
+
await estimatesApi.deleteEstimateReport(projectId, costReportUid);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (translationJobUid) {
|
|
156
|
+
// A job can only be deleted once it's CANCELLED.
|
|
157
|
+
await jobsApi.cancelJob(
|
|
158
|
+
projectId,
|
|
159
|
+
translationJobUid,
|
|
160
|
+
new CancelJobParameters().setReason("api-sdk-nodejs integration test cleanup")
|
|
161
|
+
);
|
|
162
|
+
await jobsApi.deleteJob(projectId, translationJobUid);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (fileUri) {
|
|
166
|
+
await filesApi.deleteFile(projectId, fileUri);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
async function waitForReportCompletion(reportUid: string): Promise<void> {
|
|
171
|
+
for (let attempt = 0; attempt < 30; attempt += 1) {
|
|
172
|
+
/* eslint-disable-next-line no-await-in-loop */
|
|
173
|
+
const status = await estimatesApi.getEstimateReportStatus(projectId, reportUid);
|
|
174
|
+
|
|
175
|
+
logResponse("getEstimateReportStatus", status);
|
|
176
|
+
|
|
177
|
+
if (TERMINAL_REPORT_STATUSES.includes(status.reportStatus)) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* eslint-disable-next-line no-await-in-loop */
|
|
182
|
+
await delay(3000);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
throw new Error(`Timed out waiting for report ${reportUid} to complete`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
it("generates, reads, lists, tags, downloads and deletes a fuzzy estimate report", async () => {
|
|
189
|
+
const generated = await estimatesApi.generateJobFuzzyEstimateReport(
|
|
190
|
+
projectId,
|
|
191
|
+
translationJobUid,
|
|
192
|
+
new GenerateJobEstimateReportParameters().setContentType(JobContentType.ALL_CONTENT)
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
logResponse("generateJobFuzzyEstimateReport", generated);
|
|
196
|
+
assert.ok(generated.reportUid);
|
|
197
|
+
|
|
198
|
+
const { reportUid } = generated;
|
|
199
|
+
|
|
200
|
+
fuzzyReportUid = reportUid;
|
|
201
|
+
|
|
202
|
+
await waitForReportCompletion(reportUid);
|
|
203
|
+
|
|
204
|
+
const report = await estimatesApi.getEstimateReport(projectId, reportUid);
|
|
205
|
+
|
|
206
|
+
logResponse("getEstimateReport", report);
|
|
207
|
+
assert.equal(report.reportUid, reportUid);
|
|
208
|
+
assert.ok(report.totalStrings > 0, "expected non-zero totalStrings now the job has real content");
|
|
209
|
+
|
|
210
|
+
const list = await estimatesApi.getJobFuzzyEstimateReports(
|
|
211
|
+
projectId,
|
|
212
|
+
translationJobUid,
|
|
213
|
+
new ListJobEstimateReportsParameters().setLimit(10).setOffset(0)
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
logResponse("getJobFuzzyEstimateReports", list);
|
|
217
|
+
assert.ok(list.items.some((item) => item.reportUid === reportUid));
|
|
218
|
+
|
|
219
|
+
const tagged = await estimatesApi.modifyEstimateReportTags(
|
|
220
|
+
projectId,
|
|
221
|
+
reportUid,
|
|
222
|
+
new ModifyEstimateReportTagsParameters().setTags(["api-sdk-nodejs-integration"])
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
logResponse("modifyEstimateReportTags", tagged);
|
|
226
|
+
assert.deepEqual(tagged.tags, ["api-sdk-nodejs-integration"]);
|
|
227
|
+
|
|
228
|
+
const downloaded = await estimatesApi.downloadEstimateReport(projectId, reportUid);
|
|
229
|
+
|
|
230
|
+
logResponse("downloadEstimateReport", `<${downloaded.byteLength} bytes>`);
|
|
231
|
+
assert.ok(downloaded.byteLength > 0);
|
|
232
|
+
|
|
233
|
+
await estimatesApi.deleteEstimateReport(projectId, reportUid);
|
|
234
|
+
fuzzyReportUid = undefined;
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("generates and reads a cost estimate report", async () => {
|
|
238
|
+
const generated = await estimatesApi.generateJobCostEstimateReport(
|
|
239
|
+
projectId,
|
|
240
|
+
translationJobUid,
|
|
241
|
+
new GenerateJobEstimateReportParameters().setContentType(JobContentType.ALL_CONTENT)
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
logResponse("generateJobCostEstimateReport", generated);
|
|
245
|
+
assert.ok(generated.reportUid);
|
|
246
|
+
|
|
247
|
+
const { reportUid } = generated;
|
|
248
|
+
|
|
249
|
+
costReportUid = reportUid;
|
|
250
|
+
|
|
251
|
+
await waitForReportCompletion(reportUid);
|
|
252
|
+
|
|
253
|
+
const report = await estimatesApi.getEstimateReport(projectId, reportUid);
|
|
254
|
+
|
|
255
|
+
logResponse("getEstimateReport (cost)", report);
|
|
256
|
+
assert.equal(report.reportUid, reportUid);
|
|
257
|
+
assert.ok(report.totalStrings > 0, "expected non-zero totalStrings now the job has real content");
|
|
258
|
+
|
|
259
|
+
const list = await estimatesApi.getJobCostEstimateReports(
|
|
260
|
+
projectId,
|
|
261
|
+
translationJobUid,
|
|
262
|
+
new ListJobEstimateReportsParameters().setLimit(10).setOffset(0)
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
logResponse("getJobCostEstimateReports", list);
|
|
266
|
+
assert.ok(list.items.some((item) => item.reportUid === reportUid));
|
|
267
|
+
|
|
268
|
+
await estimatesApi.deleteEstimateReport(projectId, reportUid);
|
|
269
|
+
costReportUid = undefined;
|
|
270
|
+
});
|
|
271
|
+
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
const logResponsesEnabled = process.env.SMARTLING_LOG_RESPONSES === "true";
|
|
2
|
-
|
|
3
1
|
export function logResponse(label: string, response: unknown): void {
|
|
4
|
-
|
|
2
|
+
// Read fresh on every call rather than freezing into a module-level constant at import
|
|
3
|
+
// time: this module is `require`d (by each spec file's own imports) before that same
|
|
4
|
+
// spec file's `dotenv.config()` call runs, and the require is cached - so a constant
|
|
5
|
+
// computed once here would always see pre-dotenv env vars, regardless of .env's content.
|
|
6
|
+
if (process.env.SMARTLING_LOG_RESPONSES !== "true") {
|
|
5
7
|
return;
|
|
6
8
|
}
|
|
7
9
|
|
|
@@ -7,6 +7,8 @@ import { CreateStringSearchFilterParameters } from "../../api/translation-memory
|
|
|
7
7
|
import { BulkExportTmStringsParameters } from "../../api/translation-memory/params/bulk-export-tm-strings-parameters";
|
|
8
8
|
import { CreateTmParameters } from "../../api/translation-memory/params/create-tm-parameters";
|
|
9
9
|
import { UpdateTmParameters } from "../../api/translation-memory/params/update-tm-parameters";
|
|
10
|
+
import { SearchTmsParameters } from "../../api/translation-memory/params/search-tms-parameters";
|
|
11
|
+
import { TmSorting } from "../../api/translation-memory/params/tm-sorting";
|
|
10
12
|
import { TranslationQualityType } from "../../api/translation-memory/params/translation-quality-type";
|
|
11
13
|
import { logResponse } from "./helpers/log-response";
|
|
12
14
|
|
|
@@ -32,6 +34,7 @@ describe("SmartlingTranslationMemoryApi integration tests.", function integratio
|
|
|
32
34
|
|
|
33
35
|
let api: SmartlingTranslationMemoryApi;
|
|
34
36
|
let tmUid: string;
|
|
37
|
+
let tmName: string;
|
|
35
38
|
|
|
36
39
|
before(function skipWithoutCredentials() {
|
|
37
40
|
if (!hasCredentials) {
|
|
@@ -47,10 +50,12 @@ describe("SmartlingTranslationMemoryApi integration tests.", function integratio
|
|
|
47
50
|
});
|
|
48
51
|
|
|
49
52
|
before(async () => {
|
|
53
|
+
tmName = `api-sdk-nodejs integration test TM ${Date.now()}`;
|
|
54
|
+
|
|
50
55
|
const created = await api.createTm(
|
|
51
56
|
accountUid,
|
|
52
57
|
new CreateTmParameters()
|
|
53
|
-
.setName(
|
|
58
|
+
.setName(tmName)
|
|
54
59
|
.setDescription("Created by the api-sdk-nodejs integration suite")
|
|
55
60
|
.setSourceLocaleId("en-US")
|
|
56
61
|
.setTranslationQuality(TranslationQualityType.TRANSLATION)
|
|
@@ -83,6 +88,11 @@ describe("SmartlingTranslationMemoryApi integration tests.", function integratio
|
|
|
83
88
|
|
|
84
89
|
logResponse("updateTm", updated);
|
|
85
90
|
|
|
91
|
+
// Keep tmName in sync with the TM's current name before any assertion below can throw,
|
|
92
|
+
// so a later nameFilter-based searchTms lookup (see "Finds the TM via searchTms") still
|
|
93
|
+
// matches the renamed TM even if one of those assertions fails.
|
|
94
|
+
tmName = updatedName;
|
|
95
|
+
|
|
86
96
|
assert.ok(updated, "updateTm returned null");
|
|
87
97
|
assert.equal(updated.tmUid, tmUid);
|
|
88
98
|
assert.equal(updated.name, updatedName);
|
|
@@ -91,6 +101,47 @@ describe("SmartlingTranslationMemoryApi integration tests.", function integratio
|
|
|
91
101
|
assert.ok(updated.lastModified instanceof Date);
|
|
92
102
|
});
|
|
93
103
|
|
|
104
|
+
it("Gets the TM by UID", async () => {
|
|
105
|
+
const fetched = await api.getTm(accountUid, tmUid);
|
|
106
|
+
|
|
107
|
+
logResponse("getTm", fetched);
|
|
108
|
+
|
|
109
|
+
assert.ok(fetched, "getTm returned null");
|
|
110
|
+
assert.equal(fetched.tmUid, tmUid);
|
|
111
|
+
assert.ok(fetched.created instanceof Date);
|
|
112
|
+
assert.ok(fetched.lastModified instanceof Date);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("Finds the TM via searchTms", async () => {
|
|
116
|
+
// Captured as a const so the polling loop's closure below doesn't trip no-loop-func.
|
|
117
|
+
const expectedTmUid = tmUid;
|
|
118
|
+
const searchParams = (): SearchTmsParameters => new SearchTmsParameters()
|
|
119
|
+
.setSourceLocaleId("en-US")
|
|
120
|
+
.setNameFilter(tmName)
|
|
121
|
+
.setSortBy(TmSorting.BY_NAME_ASC)
|
|
122
|
+
.setFirst(50);
|
|
123
|
+
|
|
124
|
+
// A just-created TM can briefly miss nameFilter-based search before it's indexed,
|
|
125
|
+
// so retry until it shows up or the deadline passes.
|
|
126
|
+
let found = await api.searchTms(accountUid, searchParams());
|
|
127
|
+
const deadline = Date.now() + 30000;
|
|
128
|
+
|
|
129
|
+
while (
|
|
130
|
+
!found?.some((tm) => tm?.tmUid === expectedTmUid)
|
|
131
|
+
&& Date.now() < deadline
|
|
132
|
+
) {
|
|
133
|
+
/* eslint-disable-next-line no-await-in-loop */
|
|
134
|
+
await delay(2000);
|
|
135
|
+
/* eslint-disable-next-line no-await-in-loop */
|
|
136
|
+
found = await api.searchTms(accountUid, searchParams());
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
logResponse("searchTms", found);
|
|
140
|
+
|
|
141
|
+
assert.ok(found, "searchTms returned null");
|
|
142
|
+
assert.ok(found.some((tm) => tm?.tmUid === expectedTmUid), "searchTms did not return the TM created by this suite");
|
|
143
|
+
});
|
|
144
|
+
|
|
94
145
|
it("Imports a TMX file", async () => {
|
|
95
146
|
const result = await api.importTmxFile(
|
|
96
147
|
accountUid,
|
|
@@ -11,6 +11,8 @@ import { BulkExportTmStringsParameters } from "../api/translation-memory/params/
|
|
|
11
11
|
import { ExtendedExportMetadataType } from "../api/translation-memory/params/extended-export-metadata-type";
|
|
12
12
|
import { CreateTmParameters } from "../api/translation-memory/params/create-tm-parameters";
|
|
13
13
|
import { UpdateTmParameters } from "../api/translation-memory/params/update-tm-parameters";
|
|
14
|
+
import { SearchTmsParameters } from "../api/translation-memory/params/search-tms-parameters";
|
|
15
|
+
import { TmSorting } from "../api/translation-memory/params/tm-sorting";
|
|
14
16
|
import { TranslationQualityType } from "../api/translation-memory/params/translation-quality-type";
|
|
15
17
|
import { LeverageType } from "../api/translation-memory/params/leverage-type";
|
|
16
18
|
import { SourceType } from "../api/translation-memory/params/source-type";
|
|
@@ -26,7 +28,9 @@ function formDataText(formData: { _streams: Array<unknown> }): string {
|
|
|
26
28
|
|
|
27
29
|
const noRequestIdHeaders = { get: (): string | null => null };
|
|
28
30
|
|
|
29
|
-
function tmGraphQlResponseMock(
|
|
31
|
+
function tmGraphQlResponseMock(
|
|
32
|
+
operationName: string, tm: Record<string, unknown> | Array<Record<string, unknown>>
|
|
33
|
+
): {
|
|
30
34
|
status: number;
|
|
31
35
|
headers: { get: (name: string) => string | null };
|
|
32
36
|
text: () => Promise<string>;
|
|
@@ -758,6 +762,80 @@ describe("SmartlingTranslationMemoryApi class tests.", () => {
|
|
|
758
762
|
assert.equal(result.tmUid, "j45v1uvsi3tx");
|
|
759
763
|
});
|
|
760
764
|
|
|
765
|
+
it("Get TM", async () => {
|
|
766
|
+
fetchStub.returns(tmGraphQlResponseMock("tm", sampleTm));
|
|
767
|
+
|
|
768
|
+
const result = await translationMemoryApi.getTm(accountUid, "j45v1uvsi3tx");
|
|
769
|
+
|
|
770
|
+
const sentBody = JSON.parse(fetchStub.getCall(0).args[1].body);
|
|
771
|
+
assert.deepEqual(sentBody.variables, { tmUid: "j45v1uvsi3tx" });
|
|
772
|
+
assert.ok(sentBody.query.includes("tm(tmUid: $tmUid)"));
|
|
773
|
+
|
|
774
|
+
assert.ok(result);
|
|
775
|
+
assert.equal(result.tmUid, "j45v1uvsi3tx");
|
|
776
|
+
assert.ok(result.created instanceof Date);
|
|
777
|
+
assert.ok(result.lastModified instanceof Date);
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
it("Get TM: a null result is returned as null, not thrown", async () => {
|
|
781
|
+
fetchStub.returns({
|
|
782
|
+
status: 200,
|
|
783
|
+
headers: noRequestIdHeaders,
|
|
784
|
+
text: async (): Promise<string> => JSON.stringify({ data: { tm: null } })
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
const result = await translationMemoryApi.getTm(accountUid, "missingTmUid");
|
|
788
|
+
|
|
789
|
+
assert.equal(result, null);
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
it("Search TMs: exercises every SearchTmsParameters setter", async () => {
|
|
793
|
+
fetchStub.returns(tmGraphQlResponseMock("searchTms", [sampleTm]));
|
|
794
|
+
|
|
795
|
+
const params = new SearchTmsParameters()
|
|
796
|
+
.setFirst(25)
|
|
797
|
+
.setOffset(10)
|
|
798
|
+
.setSortBy(TmSorting.BY_NAME_DESC)
|
|
799
|
+
.setSourceLocaleId("en-US")
|
|
800
|
+
.setNameFilter("Marketing")
|
|
801
|
+
.setSourceLanguageId("en")
|
|
802
|
+
.setTranslationQuality(TranslationQualityType.TRANSLATION);
|
|
803
|
+
|
|
804
|
+
const result = await translationMemoryApi.searchTms(accountUid, params);
|
|
805
|
+
|
|
806
|
+
const sentBody = JSON.parse(fetchStub.getCall(0).args[1].body);
|
|
807
|
+
assert.deepEqual(sentBody.variables, {
|
|
808
|
+
searchTmFilter: {
|
|
809
|
+
first: 25,
|
|
810
|
+
offset: 10,
|
|
811
|
+
sortBy: "BY_NAME_DESC",
|
|
812
|
+
sourceLocaleId: "en-US",
|
|
813
|
+
nameFilter: "Marketing",
|
|
814
|
+
sourceLanguageId: "en",
|
|
815
|
+
translationQuality: "TRANSLATION"
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
assert.ok(sentBody.query.includes("searchTms(searchTmFilter: $searchTmFilter)"));
|
|
819
|
+
|
|
820
|
+
assert.ok(result);
|
|
821
|
+
assert.equal(result.length, 1);
|
|
822
|
+
assert.equal(result?.[0]?.tmUid, "j45v1uvsi3tx");
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
it("Search TMs: a null result is returned as null, not thrown", async () => {
|
|
826
|
+
fetchStub.returns({
|
|
827
|
+
status: 200,
|
|
828
|
+
headers: noRequestIdHeaders,
|
|
829
|
+
text: async (): Promise<string> => JSON.stringify({ data: { searchTms: null } })
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
const result = await translationMemoryApi.searchTms(
|
|
833
|
+
accountUid, new SearchTmsParameters()
|
|
834
|
+
);
|
|
835
|
+
|
|
836
|
+
assert.equal(result, null);
|
|
837
|
+
});
|
|
838
|
+
|
|
761
839
|
it("Create string search: exercises every CreateStringSearchFilterParameters setter", () => {
|
|
762
840
|
const translationDateRangeStart = new Date("2026-01-01T00:00:00Z");
|
|
763
841
|
const translationDateRangeEnd = new Date("2026-02-01T00:00:00Z");
|