Skip to content

Commit

Permalink
Merge pull request #80 from transifex/validate-empty-keys-strings
Browse files Browse the repository at this point in the history
Ignore empty keys when pushing strings
  • Loading branch information
Nikos Vasileiou authored Jul 7, 2023
2 parents 9c3548e + 7d23e93 commit d6d7632
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 20 deletions.
50 changes: 33 additions & 17 deletions src/helpers/validators.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
const joi = require('joi');

const PUSH_SOURCE_CONTENT_SCHEMA = joi.object().keys({
data: joi.object().pattern(/./, joi.object().keys(
{
string: joi.string().allow(''),
meta: joi.any(),
},
)).required(),
meta: joi.object().keys({
purge: joi.boolean(),
override_tags: joi.boolean(),
override_occurrences: joi.boolean(),
keep_translations: joi.boolean(),
dry_run: joi.boolean(),
}),
const PUSH_SOURCE_CONTENT_ROOT_SCHEMA = joi.object().keys({
data: joi.object().required(),
meta: joi.object(),
}).required();

const PUSH_SOURCE_CONTENT_DATA_SCHEMA = joi.object().pattern(/./, joi.object().keys(
{
string: joi.string().allow(''),
meta: joi.any(),
},
)).required();

const PUSH_SOURCE_CONTENT_META_SCHEMA = joi.object().keys({
purge: joi.boolean(),
override_tags: joi.boolean(),
override_occurrences: joi.boolean(),
keep_translations: joi.boolean(),
dry_run: joi.boolean(),
});

/**
Expand Down Expand Up @@ -41,11 +45,23 @@ function handleResult(error, isWeb) {
}
}

function validatePushSourceContent(payload) {
const { error } = joi.validate(payload, PUSH_SOURCE_CONTENT_SCHEMA);
function validatePushSourceContentRoot(payload) {
const { error } = joi.validate(payload, PUSH_SOURCE_CONTENT_ROOT_SCHEMA);
handleResult(error, true);
}

function validatePushSourceContentData(payload) {
const { error } = joi.validate(payload, PUSH_SOURCE_CONTENT_DATA_SCHEMA);
handleResult(error, true);
}

function validatePushSourceContentMeta(payload) {
const { error } = joi.validate(payload, PUSH_SOURCE_CONTENT_META_SCHEMA);
handleResult(error, true);
}

module.exports = {
validatePushSourceContent,
validatePushSourceContentRoot,
validatePushSourceContentData,
validatePushSourceContentMeta,
};
4 changes: 3 additions & 1 deletion src/services/syncer/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ async function getProjectLanguageTranslations(options, langCode) {
* }
*/
async function pushSourceContent(options, payload) {
validators.validatePushSourceContent(payload);
validators.validatePushSourceContentRoot(payload);
validators.validatePushSourceContentMeta(payload.meta);

// Remove empty keys and empty strings from payload
// There are several Native SDKs that might send invalid
Expand All @@ -122,6 +123,7 @@ async function pushSourceContent(options, payload) {
cleanData[key] = value;
}
});
validators.validatePushSourceContentData(cleanData);

// Send valid payload to syncer
const data = await syncer.pushSourceContent(
Expand Down
55 changes: 53 additions & 2 deletions tests/routes/content.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ describe('POST /content', () => {
{
someotherkey: 'somevalue',
},
{
'hello\n你好世\n': 'somevalue',
},
],
});

Expand All @@ -360,7 +363,9 @@ describe('POST /content', () => {
.send({
data: {
...data,
' ': { string: 'empty key' },
'hello\n你好世\n': { string: 'somevalue' },
'': { string: 'empty key' },
' ': { string: 'key as space' },
' ': { string: '' },
'Empty string key': { string: '' },
},
Expand All @@ -383,7 +388,7 @@ describe('POST /content', () => {
expect(res.body).to.eqls({
data: {
details: {
created: 2,
created: 3,
updated: 0,
skipped: 0,
deleted: 0,
Expand Down Expand Up @@ -564,6 +569,52 @@ describe('POST /content', () => {
});
});

it('should not throw an error if data has no strings', async () => {
const sourceData = dataHelper.getSourceString();
nock(urls.api)
.get(urls.source_strings)
.reply(200, sourceData);
nock(urls.api)
.get(urls.source_strings_revisions)
.reply(200, { data: [], links: {} });

nock(urls.api)
.post(urls.resource_strings)
.reply(200, {});

let res = await request(app)
.post('/content')
.set('Accept-version', 'v2')
.set('Authorization', `Bearer ${token}:secret`)
.send({ data: {} });

// poll
let status = '';
const jobUrl = res.body.data.links.job;
while (status !== 'completed') {
await sleep(100);
res = await request(app)
.get(jobUrl)
.set('Authorization', `Bearer ${token}:secret`);
expect(res.status).to.eql(200);
status = res.body.data.status;
}

expect(res.body).to.eqls({
data: {
details: {
created: 0,
updated: 0,
skipped: 0,
deleted: 0,
failed: 0,
},
errors: [],
status: 'completed',
},
});
});

it('should patch source strings if new', async () => {
const sourceData = dataHelper.getSourceString();
nock(urls.api)
Expand Down

0 comments on commit d6d7632

Please sign in to comment.