-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Harden test-cases and align with other implementations #84
Conversation
This commit refactors and adds more tests to the `parse()` implementation to align with similar libraries's behaviour, e.g.: - https://github.com/Microsoft/node-fast-plist - https://docs.python.org/3/library/plistlib.html With the new tests a few of the tests were failing: ``` 31 passing (177ms) 10 failing 1) parse() real should throw an Error when parsing an empty real: AssertionError: Missing expected exception.. 2) parse() string should parse a self closing string: AssertionError: null === '' 3) parse() string should parse an empty string: AssertionError: null === '' 4) parse() string should parse a string with comments: AssertionError: 'a comment string' === 'a string' 5) parse() array should parse empty elements inside an array: AssertionError: [ false ] deepEqual [ '', false ] 6) parse() dict should throw if key is missing: AssertionError: Missing expected exception.. 7) parse() dict should throw if two keys follow each other: AssertionError: Missing expected exception.. 8) parse() dict should throw if value is missing: AssertionError: Missing expected exception.. 9) parse() dict should parse an empty key: AssertionError: {} deepEqual { '': '1' } 10) parse() dict should parse an empty value: AssertionError: { a: null } deepEqual { a: '' } ``` This commit also refactors the `lib/parse.js` to pass these tests. When executing the new implementation of `lib/parse.js` agains the old tests the following tests were failing: ``` 25 passing (143ms) 3 failing 1) plist parse() should parse an empty <key/> in a dictionary: AssertionError: false == true 2) plist parse() should parse an empty <key></key> in a dictionary: AssertionError: false == true 3) plist parse() should parse an empty <key></key> and <string></string> in dictionary with more data: AssertionError: { '': '', UIRequiredDeviceCapabilities: [ 'armv7' ] } deepEqual { UIRequiredDeviceCapabilities: [ 'armv7' ] } ``` As the output above shows, most of the issue are with the handling of empty strings and empty dictionary keys. Added with the new implementation are custom Errors for unexpected input, better handling of comments inside tags and a more aligned handling of empty keys/strings.
The browser tests are failing because of: https://docs.travis-ci.com/user/pull-requests#Pull-Requests-and-Security-Restrictions |
@TooTallNate @mreinstein ping, any update on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ZauberNerd overall, good changes. I'm sorry it took so long to get around to this. most of my comments are fairly trivial.
Another issue is I'd like to ensure the tests pass.
lib/parse.js
Outdated
// ignore comment nodes (text) | ||
if (!shouldIgnoreNode(node.childNodes[i])) { | ||
new_arr.push( parsePlistXML(node.childNodes[i])); | ||
if (!isEmptyNode(node)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to return early rather than wrap the whole thing in an if
block. results in less nesting. e.g.,
if(isEmptyNode(node)) {
return [];
}
It also eliminates the "not" modifier (!
) which makes the if condition ever-so-slightly easier to read.
lib/parse.js
Outdated
if (!shouldIgnoreNode(node.childNodes[i])) { | ||
if (key === null) { | ||
counter = 0; | ||
if (!isEmptyNode(node)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here in terms of early return.
lib/parse.js
Outdated
if (!shouldIgnoreNode(node.childNodes[i])) { | ||
res = parsePlistXML(node.childNodes[i]); | ||
if (null != res) new_arr.push(res); | ||
if (!isEmptyNode(node)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another early return opportunity
lib/parse.js
Outdated
res = ''; | ||
if(node.childNodes[0]) { | ||
if(!isEmptyNode(node)) { | ||
res = node.childNodes[0].nodeValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another early return opportunity. I think you can just return node.childNodes[0].nodeValue
rather than filling a variable and returning that?
lib/parse.js
Outdated
if(!isEmptyNode(node)) { | ||
for (i=0; i < node.childNodes.length; i++) { | ||
var type = node.childNodes[i].nodeType; | ||
if (type === 3 || type === 4) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than using these magic numbers 3
and 4
can you define them as node type constants?
lib/parse.js
Outdated
if (node.childNodes[d].nodeType === 3) { | ||
res += node.childNodes[d].nodeValue; | ||
for (i=0; i < node.childNodes.length; i++) { | ||
if (node.childNodes[i].nodeType === 3) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know you didn't write this code; it pre-dates your additions. But while you're in here, can you replace the magic number usage here too?
lib/parse.js
Outdated
for (d=0; d < node.childNodes.length; d++) { | ||
if (node.childNodes[d].nodeType === 3) { | ||
res += node.childNodes[d].nodeValue.replace(/\s+/g, ''); | ||
if (!isEmptyNode(node)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another early return opportunity I think
40aae71
to
792b920
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changes look good. I'll merge after this change
lib/parse.js
Outdated
@@ -10,6 +10,12 @@ var DOMParser = require('xmldom').DOMParser; | |||
|
|||
exports.parse = parse; | |||
|
|||
var NODE_TYPES = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's do these instead please:
TEXT_NODE = 3
CDATA_NODE = 4
COMMENT_NODE = 8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, will do.
Btw: https://docs.travis-ci.com/user/sauce-connect/ and https://docs.travis-ci.com/user/jwt might help with getting the sauce labs tests to run for PRs from forks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I have access to sauce, nor am I familiar with the service in great detail. @TooTallNate care to take this on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise we could just disable them for PRs - I think they'll still be run on master merge, see this section: https://docs.travis-ci.com/user/pull-requests#Pull-Requests-and-Security-Restrictions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah but the problem with that is it's more work to verify PRs are good before they're merged. I would rather not merge anything to master and have the tests fail after the fact.
792b920
to
7619537
Compare
@ZauberNerd can you open a separate issue for the sauce labs change please? |
@mreinstein do you have an idea when you are going to release a new version to npm with these changes included? |
The `plist` module had a bug when parsing an empty key which has since been fixed and released in a new version. This commit updates the `plist` dependency to the latest version in order to remove a fix we had to introduce in this project to work around that issue. Ref: TooTallNate/plist.js#84
@ZauberNerd sorry for the crazy long reply delay. I'm hoping to lump together all of these changes that are considered "API breaking" in the next version (v4) |
This commit refactors and adds more tests to the
parse()
implementationto align with similar libraries's behaviour, e.g.:
When running the new test suite against the old
lib/parse.js
implementationa few tests were failing:
When executing the new implementation of
lib/parse.js
agains the oldtests the following tests were failing:
As the output above shows, most of the issue are with the handling of
empty strings and empty dictionary keys.
Added with the new implementation are custom Errors for invalid
input, better handling of comments inside tags and a more aligned
handling of empty keys/strings.
I know this is a huge change, so I'd understand if you're hesitant to merge this,
but let me know your thoughts.
Initially I only wanted to fix the handling of empty strings/keys but then I got a bit carried away.
Related issues: #79 #71 #66 #81 #80 #67