Skip to content

Commit

Permalink
Add public function to normalize device-info field values (#129)
Browse files Browse the repository at this point in the history
* Normalize device-info field values

* fix broken tests

* restore working package-lock
  • Loading branch information
TwitchBronBron authored Nov 20, 2023
1 parent c522ed1 commit 56bdff7
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 20 deletions.
23 changes: 23 additions & 0 deletions src/RokuDeploy.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,29 @@ describe('index', () => {
});
});

describe('normalizeDeviceInfoFieldValue', () => {
it('converts normal values', () => {
expect(rokuDeploy.normalizeDeviceInfoFieldValue('true')).to.eql(true);
expect(rokuDeploy.normalizeDeviceInfoFieldValue('false')).to.eql(false);
expect(rokuDeploy.normalizeDeviceInfoFieldValue('1')).to.eql(1);
expect(rokuDeploy.normalizeDeviceInfoFieldValue('1.2')).to.eql(1.2);
//it'll trim whitespace too
expect(rokuDeploy.normalizeDeviceInfoFieldValue(' 1.2')).to.eql(1.2);
expect(rokuDeploy.normalizeDeviceInfoFieldValue(' 1.2 ')).to.eql(1.2);
});

it('leaves invalid numbers as strings', () => {
expect(rokuDeploy.normalizeDeviceInfoFieldValue('v1.2.3')).to.eql('v1.2.3');
expect(rokuDeploy.normalizeDeviceInfoFieldValue('1.2.3-alpha.1')).to.eql('1.2.3-alpha.1');
expect(rokuDeploy.normalizeDeviceInfoFieldValue('123Four')).to.eql('123Four');
});

it('decodes HTML entities', () => {
expect(rokuDeploy.normalizeDeviceInfoFieldValue('3&4')).to.eql('3&4');
expect(rokuDeploy.normalizeDeviceInfoFieldValue('3&4')).to.eql('3&4');
});
});


describe('getDevId', () => {
it('should return the current Dev ID if successful', async () => {
Expand Down
42 changes: 22 additions & 20 deletions src/RokuDeploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1011,27 +1011,10 @@ export class RokuDeploy {
} as Record<string, any>;

if (options.enhance) {
// convert 'true' and 'false' string values to boolean
for (let key in deviceInfo) {
if (deviceInfo[key] === 'true') {
deviceInfo[key] = true;
} else if (deviceInfo[key] === 'false') {
deviceInfo[key] = false;
}
}

// convert the following string values into numbers
const numberFields = ['software-build', 'uptime', 'trc-version', 'av-sync-calibration-enabled', 'time-zone-offset'];
for (const field of numberFields) {
if (deviceInfo.hasOwnProperty(field)) {
deviceInfo[field] = parseInt(deviceInfo[field]);
}
}

//convert the property names to camel case
const result = {};
for (const key in deviceInfo) {
result[lodash.camelCase(key)] = deviceInfo[key];
// sanitize/normalize values to their native formats, and also convert property names to camelCase
for (let key in deviceInfo) {
result[lodash.camelCase(key)] = this.normalizeDeviceInfoFieldValue(deviceInfo[key]);
}
deviceInfo = result;
}
Expand All @@ -1041,6 +1024,25 @@ export class RokuDeploy {
}
}

/**
* Normalize a deviceInfo field value. This includes things like converting boolean strings to booleans, number strings to numbers,
* decoding HtmlEntities, etc.
* @param deviceInfo
*/
public normalizeDeviceInfoFieldValue(value: any) {
let num: number;
// convert 'true' and 'false' string values to boolean
if (value === 'true') {
return true;
} else if (value === 'false') {
return false;
} else if (value.trim() !== '' && !isNaN(num = Number(value))) {
return num;
} else {
return util.decodeHtmlEntities(value);
}
}

public async getDevId(options?: RokuDeployOptions) {
const deviceInfo = await this.getDeviceInfo(options as any);
return deviceInfo['keyed-developer-id'];
Expand Down
11 changes: 11 additions & 0 deletions src/util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,4 +274,15 @@ describe('util', () => {
).to.eql('some-host');
});
});

describe('decodeHtmlEntities', () => {
it('decodes values properly', () => {
expect(util.decodeHtmlEntities('&nbsp;')).to.eql(' ');
expect(util.decodeHtmlEntities('&amp;')).to.eql('&');
expect(util.decodeHtmlEntities('&quot;')).to.eql('"');
expect(util.decodeHtmlEntities('&lt;')).to.eql('<');
expect(util.decodeHtmlEntities('&gt;')).to.eql('>');
expect(util.decodeHtmlEntities('&#39;')).to.eql(`'`);
});
});
});
22 changes: 22 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,28 @@ export class Util {
}

private dnsCache = new Map<string, string>();

/**
* Decode HTML entities like &nbsp; &#39; to its original character
*/
public decodeHtmlEntities(encodedString: string) {
let translateRegex = /&(nbsp|amp|quot|lt|gt);/g;
let translate = {
'nbsp': ' ',
'amp': '&',
'quot': '"',
'lt': '<',
'gt': '>'
};

return encodedString.replace(translateRegex, (match, entity) => {
return translate[entity];
}).replace(/&#(\d+);/gi, (match, numStr) => {
let num = parseInt(numStr, 10);
return String.fromCharCode(num);
});
}

}

export let util = new Util();
Expand Down

0 comments on commit 56bdff7

Please sign in to comment.