Loading the parity record
Fetching the measured run — the pinned upstream oracle, every symbol and every case.
Fetching the measured run — the pinned upstream oracle, every symbol and every case.
Parity / cheerio
Every number on this page was produced by running both implementations over the same cases: the real cheerio package pinned at 1.0.0 answers first, and its answer is the expectation the Go port is held to. Nothing is a hand-written expectation, so a new upstream release re-scores the port on its own. See cheerio for the port's own documentation. Source: github.com/malcolmston/cheerio.
Not a generic diagram: every node below names an artefact of this harness — the pinned package it installed, the runner files it started, the case files it streamed, and the counts it wrote out.
| Case group | Cases | Match | Mismatch | Group parity |
|---|---|---|---|---|
| selectors | 83 | 82 | 0 | 98.8% |
| accessors | 55 | 53 | 0 | 96.4% |
| manipulation | 48 | 47 | 0 | 97.9% |
| parsing | 46 | 43 | 2 | 93.5% |
| traversal | 45 | 45 | 0 | 100.0% |
| forms-and-statics | 20 | 17 | 0 | 85.0% |
| serialisation | 20 | 19 | 0 | 95.0% |
Every exported symbol of the upstream package, and what the port offers for it. The upstream list is derived mechanically, never from a README: node -e "
const c = require('cheerio');
console.log('MODULE:', Object.keys(c).sort().join(' '));
const \$ = c.load('<div/>');
console.log('DOLLAR:', Object.getOwnPropertyNames(\$).sort().join(' '));
let p = \$.fn, out = new Set();
while (p && p !== Object.prototype) { Object.getOwnPropertyNames(p).forEach(n => out.add(n)); p = Object.getPrototypeOf(p); }
console.log('PROTO(' + out.size + '):', [...out].sort().join(' '));
". A symbol with no case is untested, never a match.
| Upstream symbol | Go symbol | Status | Cases | Note |
|---|---|---|---|---|
| add | Selection.Add / Selection.AddSelection | match | tr-add, tr-add-selection | |
| addBack | Selection.AddBack | differs | tr-add-back, tr-add-back-filtered | Go drops the previous stage: returns only the current set |
| addClass | Selection.AddClass | differs | man-addclass, man-addclass-dup, man-addclass-no-attr | Go rewrites the whole class attribute, collapsing the original inter-token whitespace |
| after | Selection.After / AfterNodes / AfterSelection | match | man-after | |
| append | Selection.Append / AppendNodes / AppendSelection | match | man-append, man-append-multi-args, man-append-multi-target, man-append-text, man-append-into-table, man-chain-order, ser-comment-preserved, ser-void-no-close-tag | |
| appendTo | Selection.AppendTo | match | man-appendto | |
| attr | Selection.Attr / Attrs / SetAttr | differs | acc-attr-*, man-setattr, man-setattr-overwrite-order, man-setattr-escaping, ser-escape-attr-* | getter matches; the setter's serialisation escapes </> inside attribute values, upstream leaves them raw |
| before | Selection.Before / BeforeNodes / BeforeSelection | match | man-before | |
| cheerio | — | untested | — | internal marker property ("[cheerio object]") |
| children | Selection.Children | match | tr-children, tr-children-filtered, tree-void-children* | |
| clone | Selection.Clone | match | tr-clone-detached, tr-clone-independent | |
| closest | Selection.Closest | match | tr-closest-self, tr-closest-ancestor, tr-closest-miss | |
| constructor | — | untested | — | internal |
| contents | Selection.Contents | match | tr-contents, tree-comment-contents | |
| css | Selection.Css / SetCss / SetCssMap | differs | acc-css-present, acc-css-hyphenated, acc-css-no-space, acc-css-absent, man-setcss, man-setcss-new | absent property: upstream undefined, Go "" |
| data | Selection.Data / DataOr / DataMap / SetData | differs | acc-data-*, man-setdata | getters match after stringification; the **setter** diverges: cheerio caches the value in memory and never touches the DOM, the Go port writes a real data-* attribute |
| each | Selection.Each | untested | — | callback-based; not expressible over the JSON-Lines protocol |
| empty | Selection.Empty | match | man-empty | |
| end | Selection.End | differs | tr-end | Go returns the current set instead of the previous traversal stage |
| eq | Selection.Eq | match | tr-eq, tr-eq-negative, tr-eq-out-of-range | |
| extract | — | missing | — | cheerio 1.0's declarative scraping helper is not ported |
| filter | Selection.Filter / FilterMatcher | match | tr-filter | |
| filterArray | — | untested | — | internal |
| find | Selection.Find / FindMatcher | match | tr-find-nested, tr-find-dedup, comb-scoped-child, comb-scoped-adjacent, all sel-* | |
| first | Selection.First | match | tr-first, tr-first-empty | |
| get | Selection.Get | untested | — | index accessor; exercised only indirectly |
| has | Selection.Has | match | tr-has | |
| hasClass | Selection.HasClass | match | acc-hasclass-* | |
| html | Selection.Html / SetHtml | match | acc-html-*, man-sethtml*, ser-script-not-escaped, ser-style-not-escaped, tree-textarea-html | |
| index | Selection.Index / IndexSelector / IndexOfNode | match | acc-index-zero-arg, acc-index-selector, acc-index-selector-miss | |
| insertAfter | Selection.InsertAfter | match | man-insertafter | |
| insertBefore | Selection.InsertBefore | match | man-insertbefore | |
| is | Selection.Is / IsMatcher | match | acc-is-true, acc-is-false | |
| last | Selection.Last | match | tr-last | |
| map | Selection.Map / MapNodes | untested | — | callback-based |
| next | Selection.Next | match | tr-next, tr-next-filtered | |
| nextAll | Selection.NextAll | match | tr-next-all, tr-next-all-filtered | |
| nextUntil | Selection.NextUntil | match | tr-next-until, tr-next-until-filtered | |
| not | Selection.Not | match | tr-not | |
| parent | Selection.Parent | match | tr-parent, tr-parent-filtered-miss | |
| parents | Selection.Parents | match | tr-parents, tr-parents-filtered, tr-parents-multi-origin | |
| parentsUntil | Selection.ParentsUntil | match | tr-parents-until, tr-parents-until-filtered | |
| prepend | Selection.Prepend / PrependNodes / PrependSelection | match | man-prepend | |
| prependTo | Selection.PrependTo | match | man-prependto | |
| prev | Selection.Prev | match | tr-prev | |
| prevAll | Selection.PrevAll | match | tr-prev-all | nearest-first order agrees |
| prevUntil | Selection.PrevUntil | match | tr-prev-until | |
| prop | Selection.Prop / SetProp | match | acc-prop-*, man-setprop-bool-on, man-setprop-bool-off | equal only after the Node side stringifies booleans (see Normalisation 3) |
| remove | Selection.Remove | match | man-remove, man-remove-filtered | |
| removeAttr | Selection.RemoveAttr | match | man-removeattr, man-removeattr-absent | |
| removeClass | Selection.RemoveClass | differs | man-removeclass, man-removeclass-all-tokens, man-removeclass-zero-arg | the Go port has no zero-argument "remove every class" form |
| replaceWith | Selection.ReplaceWith / ReplaceWithNodes / ReplaceWithSelection | match | man-replacewith, man-replacewith-multi | |
| serialize | Selection.Serialize | differs | form-serialize, form-serialize-encoding | see serializeArray |
| serializeArray | Selection.SerializeArray | differs | form-serialize-array, form-serialize-inputs-only, form-serialize-select-multiple, form-serialize-empty | for a multiple select upstream submits each selected option's *text* (M1), the Go port submits its value (m1); upstream's own single-select path uses value, so this looks like an upstream inconsistency |
| siblings | Selection.Siblings | match | tr-siblings, tr-siblings-filtered | |
| slice | Selection.Slice | match | tr-slice, tr-slice-negative, tr-slice-clamped | Go requires both bounds (upstream's one-arg form has no counterpart) |
| splice | — | missing | — | Array-mutation method inherited from the array-like base; no Go analogue (Nodes/ToArray are read-only views) |
| text | Selection.Text / SetText | differs | acc-text-*, man-settext, ser-escape-text-*, tree-*-text | getter matches; the setter's serialisation emits U+00A0 literally where upstream emits |
| toArray | Selection.ToArray | untested | — | used internally by the Node runner only |
| toString | Selection.ToString | match | acc-tostring-multi | |
| toggleClass | Selection.ToggleClass | match | man-toggleclass | |
| unwrap | Selection.Unwrap | match | man-unwrap | Go takes no selector argument |
| val | Selection.Val / SetVal | differs | acc-val-*, man-setval-* | control with no value attribute: upstream undefined, Go "" |
| wrap | Selection.Wrap | match | man-wrap, man-wrap-nested | |
| wrapAll | Selection.WrapAll | match | man-wrapall | |
| wrapInner | Selection.WrapInner | match | man-wrapinner | |
| _findBySelector | — | untested | — | internal |
| _make | — | untested | — | internal |
| _makeDomArray | — | untested | — | internal |
| _parse | — | untested | — | internal |
| _render | — | untested | — | internal |
| load (cheerio.load) | cheerio.Load | differs | all 25 parse-*, all tree-* | tree-construction differences — see "Divergences" |
| $.html | Document.Html / Node.OuterHTML / cheerio.RenderNodes | differs | ser-*, static-html-*, acc-outerhtml-escapes | </> inside attribute values, doctype, entity re-escaping |
| $.text | cheerio.TextOf / Document.Text | match | static-text-nodes, static-text-empty | |
| $.root | Document.Root | match | ser-doc-text, every chain case (the initial selection) | Go's Document.Root() returns the document node, matching $.root() (its doc comment claims it returns the top-level *elements*, which is wrong) |
| $.contains | cheerio.Contains | match | static-contains-true, static-contains-false, static-contains-self | |
| $.merge | cheerio.Merge | differs | static-merge, static-merge-overlap | upstream concatenates, the Go port de-duplicates |
| $.parseHTML | cheerio.ParseHTML | differs | static-parsehtml-* | upstream returns null for ""; Go returns an empty slice |
| $.extract | — | missing | — | not ported |
| $.xml | — | missing | — | the Go port has no XML/XHTML serialisation mode |
| $.fn | — | missing | — | no plugin/extension point in the Go port |
| $.length | Selection.Length | match | acc-length, every count case | instance property, tested as a selection accessor |
| $.load | cheerio.Load | untested | — | re-exported load on the loaded instance |
| $.prototype | — | untested | — | internal |
| $._options | — | untested | — | internal |
| $._root | — | untested | — | internal |
| $.name | — | untested | — | Function.name artefact |
| cheerio.fromURL | — | missing | — | network loader; no Go equivalent |
| cheerio.loadBuffer | — | missing | — | encoding sniffing from a Buffer |
| cheerio.decodeStream | — | missing | — | streaming parser |
| cheerio.stringStream | — | missing | — | streaming parser |
| — | cheerio.Compile, cheerio.MustCompile, Matcher.Match, Matcher.String | extra | compile-ok, compile-bad-bracket, compile-bad-pseudo-paren, compile-trailing-combinator, compile-empty, compile-unknown-pseudo | pre-compiled selectors; upstream has no equivalent, so these cases compare $(selector) throwing against Compile returning an error |
| — | Document.FindMatcher, Selection.FindMatcher, FilterMatcher, IsMatcher | extra | — | pre-compiled variants |
| — | Document.Render, Node.Render, Selection.Render | extra | — | streaming serialisation to an io.Writer |
| — | Selection.Attrs, AttrOr, DataOr, DataMap | extra | acc-attr-all, acc-data-all | Attrs/DataMap stand in for upstream's no-argument attr()/data() |
| — | Selection.Even, Selection.Odd | extra | — | no cheerio counterpart |
| — | Selection.FilterFunc, Selection.MapNodes, Selection.Nodes | extra | — | Go-idiomatic callback/slice forms |
| — | Selection.IndexOfNode | extra | — | corresponds to jQuery .index(element) |
| — | Selection.OuterHtml | extra | acc-outerhtml-first, acc-outerhtml-escapes | upstream uses $.html(node) |
| — | Selection.RemoveData | extra | man-removedata | not on Cheerio.prototype in cheerio@1.0.0 |
Every case the harness streamed to both runners, with the exact upstream symbol and Go symbol it exercised. A deliberate, documented difference is a deviation and is counted apart from a mismatch.
| Case | Group | Upstream symbol | Go symbol | Status | Note |
|---|---|---|---|---|---|
| acc-text-selection | accessors | Cheerio.prototype.text | Selection.Text | match | |
| acc-text-empty-selection | accessors | Cheerio.prototype.text | Selection.Text | match | |
| acc-text-nested | accessors | Cheerio.prototype.text | Selection.Text | match | |
| acc-html-inner | accessors | Cheerio.prototype.html | Selection.Html | match | |
| acc-html-empty-selection | accessors | Cheerio.prototype.html | Selection.Html | match | |
| acc-html-with-comment | accessors | Cheerio.prototype.html | Selection.Html | match | |
| acc-tostring-multi | accessors | Cheerio.prototype.toString | Selection.ToString | match | |
| acc-outerhtml-first | accessors | $.html(node) | Selection.OuterHtml | match | |
| acc-outerhtml-escapes | accessors | $.html(node) | Selection.OuterHtml | match | |
| acc-attr-present | accessors | Cheerio.prototype.attr | Selection.Attr | match | |
| acc-attr-absent | accessors | Cheerio.prototype.attr | Selection.Attr | match | |
| acc-attr-empty-selection | accessors | Cheerio.prototype.attr | Selection.Attr | match | |
| acc-attr-all | accessors | Cheerio.prototype.attr | Selection.Attrs | match | |
| acc-attr-first-of-many | accessors | Cheerio.prototype.attr | Selection.Attr | match | |
| acc-attr-dup-source | accessors | Cheerio.prototype.attr | Selection.Attr | match | |
| acc-attr-entity-value | accessors | Cheerio.prototype.attr | Selection.Attr | match | |
| acc-prop-tagname | accessors | Cheerio.prototype.prop | Selection.Prop | match | |
| acc-prop-nodename | accessors | Cheerio.prototype.prop | Selection.Prop | match | |
| acc-prop-checked-true | accessors | Cheerio.prototype.prop | Selection.Prop | match | |
| acc-prop-checked-false | accessors | Cheerio.prototype.prop | Selection.Prop | match | |
| acc-prop-disabled | accessors | Cheerio.prototype.prop | Selection.Prop | match | |
| acc-prop-selected | accessors | Cheerio.prototype.prop | Selection.Prop | match | |
| acc-prop-textcontent | accessors | Cheerio.prototype.prop | Selection.Prop | match | |
| acc-prop-innerhtml | accessors | Cheerio.prototype.prop | Selection.Prop | match | |
| acc-prop-outerhtml | accessors | Cheerio.prototype.prop | Selection.Prop | match | |
| acc-prop-attr-fallback | accessors | Cheerio.prototype.prop | Selection.Prop | match | |
| acc-prop-unknown | accessors | Cheerio.prototype.prop | Selection.Prop | match | |
| acc-data-dashed | accessors | Cheerio.prototype.data | Selection.Data | match | |
| acc-data-camel | accessors | Cheerio.prototype.data | Selection.Data | match | |
| acc-data-number | accessors | Cheerio.prototype.data | Selection.Data | match | |
| acc-data-bool | accessors | Cheerio.prototype.data | Selection.Data | match | |
| acc-data-json | accessors | Cheerio.prototype.data | Selection.Data | match | |
| acc-data-plain | accessors | Cheerio.prototype.data | Selection.Data | match | |
| acc-data-absent | accessors | Cheerio.prototype.data | Selection.Data | match | |
| acc-data-all | accessors | Cheerio.prototype.data | Selection.DataMap | match | |
| acc-val-text-input | accessors | Cheerio.prototype.val | Selection.Val | match | |
| acc-val-textarea | accessors | Cheerio.prototype.val | Selection.Val | match | |
| acc-val-select | accessors | Cheerio.prototype.val | Selection.Val | match | |
| acc-val-option | accessors | Cheerio.prototype.val | Selection.Val | match | |
| acc-val-no-value-attr | accessors | Cheerio.prototype.val | Selection.Val | deviation | Go Val returns "" for a control with no value attribute where cheerio returns undefined; string-only accessor by design. |
| acc-hasclass-yes | accessors | Cheerio.prototype.hasClass | Selection.HasClass | match | |
| acc-hasclass-no | accessors | Cheerio.prototype.hasClass | Selection.HasClass | match | |
| acc-hasclass-partial | accessors | Cheerio.prototype.hasClass | Selection.HasClass | match | |
| acc-hasclass-any-of-many | accessors | Cheerio.prototype.hasClass | Selection.HasClass | match | |
| acc-css-present | accessors | Cheerio.prototype.css | Selection.Css | match | |
| acc-css-hyphenated | accessors | Cheerio.prototype.css | Selection.Css | match | |
| acc-css-no-space | accessors | Cheerio.prototype.css | Selection.Css | match | |
| acc-css-absent | accessors | Cheerio.prototype.css | Selection.Css | deviation | Go Css returns "" for an absent property where cheerio returns undefined; the port uses string-only accessors by design. |
| acc-tagname | accessors | Cheerio.prototype.prop | Selection.TagName | match | |
| acc-length | accessors | Cheerio.prototype.length | Selection.Length | match | |
| acc-index-zero-arg | accessors | Cheerio.prototype.index | Selection.Index | match | |
| acc-index-selector | accessors | Cheerio.prototype.index | Selection.IndexSelector | match | |
| acc-index-selector-miss | accessors | Cheerio.prototype.index | Selection.IndexSelector | match | |
| acc-is-true | accessors | Cheerio.prototype.is | Selection.Is | match | |
| acc-is-false | accessors | Cheerio.prototype.is | Selection.Is | match | |
| form-serialize-array | forms-and-statics | Cheerio.prototype.serializeArray | Selection.SerializeArray | deviation | cheerio submits a multiple-select option's text; because the options carry a value attribute the port submits the value per the HTML form-submission spec (upstream is the outlier). |
| form-serialize | forms-and-statics | Cheerio.prototype.serialize | Selection.Serialize | deviation | cheerio submits a multiple-select option's text; because the options carry a value attribute the port submits the value per the HTML form-submission spec (upstream is the outlier). |
| form-serialize-inputs-only | forms-and-statics | Cheerio.prototype.serializeArray | Selection.SerializeArray | match | |
| form-serialize-select-multiple | forms-and-statics | Cheerio.prototype.serializeArray | Selection.SerializeArray | deviation | cheerio submits a multiple-select option's text; because the options carry a value attribute the port submits the value per the HTML form-submission spec (upstream is the outlier). |
| form-serialize-empty | forms-and-statics | Cheerio.prototype.serializeArray | Selection.SerializeArray | match | |
| form-serialize-encoding | forms-and-statics | Cheerio.prototype.serialize | Selection.Serialize | match | |
| static-text-nodes | forms-and-statics | $.text | cheerio.TextOf | match | |
| static-text-empty | forms-and-statics | $.text | cheerio.TextOf | match | |
| static-html-nodes | forms-and-statics | $.html | cheerio.RenderNodes | match | |
| static-html-escapes | forms-and-statics | $.html | cheerio.RenderNodes | match | |
| static-contains-true | forms-and-statics | cheerio.contains | cheerio.Contains | match | |
| static-contains-false | forms-and-statics | cheerio.contains | cheerio.Contains | match | |
| static-contains-self | forms-and-statics | cheerio.contains | cheerio.Contains | match | |
| static-merge | forms-and-statics | cheerio.merge | cheerio.Merge | match | |
| static-merge-overlap | forms-and-statics | cheerio.merge | cheerio.Merge | match | cheerio.merge concatenates without de-duplicating |
| static-parsehtml-simple | forms-and-statics | $.parseHTML | cheerio.ParseHTML | match | |
| static-parsehtml-text | forms-and-statics | $.parseHTML | cheerio.ParseHTML | match | |
| static-parsehtml-table | forms-and-statics | $.parseHTML | cheerio.ParseHTML | match | |
| static-parsehtml-broken | forms-and-statics | $.parseHTML | cheerio.ParseHTML | match | |
| static-parsehtml-empty | forms-and-statics | $.parseHTML | cheerio.ParseHTML | match | upstream returns null for empty input |
| man-addclass | manipulation | Cheerio.prototype.addClass | Selection.AddClass | match | |
| man-addclass-dup | manipulation | Cheerio.prototype.addClass | Selection.AddClass | match | |
| man-addclass-no-attr | manipulation | Cheerio.prototype.addClass | Selection.AddClass | match | |
| man-removeclass | manipulation | Cheerio.prototype.removeClass | Selection.RemoveClass | match | |
| man-removeclass-all-tokens | manipulation | Cheerio.prototype.removeClass | Selection.RemoveClass | match | |
| man-removeclass-zero-arg | manipulation | Cheerio.prototype.removeClass | — | match | the Go port has no zero-argument remove-all form |
| man-toggleclass | manipulation | Cheerio.prototype.toggleClass | Selection.ToggleClass | match | |
| man-setattr | manipulation | Cheerio.prototype.attr | Selection.SetAttr | match | |
| man-setattr-overwrite-order | manipulation | Cheerio.prototype.attr | Selection.SetAttr | match | existing attribute keeps its source position |
| man-setattr-escaping | manipulation | Cheerio.prototype.attr | Selection.SetAttr | match | attribute-value escaping on output |
| man-removeattr | manipulation | Cheerio.prototype.removeAttr | Selection.RemoveAttr | match | |
| man-removeattr-absent | manipulation | Cheerio.prototype.removeAttr | Selection.RemoveAttr | match | |
| man-setprop-bool-on | manipulation | Cheerio.prototype.prop | Selection.SetProp | match | |
| man-setprop-bool-off | manipulation | Cheerio.prototype.prop | Selection.SetProp | match | |
| man-setdata | manipulation | Cheerio.prototype.data | Selection.SetData | match | cheerio caches data in memory rather than writing the attribute |
| man-removedata | manipulation | — | Selection.RemoveData | deviation | removeData is not part of Cheerio.prototype in cheerio@1.0.0 (upstream throws); the Go port provides it as an extra convenience method. |
| man-setcss | manipulation | Cheerio.prototype.css | Selection.SetCss | match | |
| man-setcss-new | manipulation | Cheerio.prototype.css | Selection.SetCss | match | |
| man-settext | manipulation | Cheerio.prototype.text | Selection.SetText | match | must be escaped, not parsed |
| man-sethtml | manipulation | Cheerio.prototype.html | Selection.SetHtml | match | |
| man-sethtml-multi-target | manipulation | Cheerio.prototype.html | Selection.SetHtml | match | |
| man-setval-input | manipulation | Cheerio.prototype.val | Selection.SetVal | match | |
| man-setval-textarea | manipulation | Cheerio.prototype.val | Selection.SetVal | match | |
| man-setval-select | manipulation | Cheerio.prototype.val | Selection.SetVal | match | |
| man-append | manipulation | Cheerio.prototype.append | Selection.Append | match |