diff --git a/.changeset/stale-games-lay.md b/.changeset/stale-games-lay.md new file mode 100644 index 0000000..beca84d --- /dev/null +++ b/.changeset/stale-games-lay.md @@ -0,0 +1,5 @@ +--- +"mocha-chai-rdf": patch +--- + +Allow multi-pointers in matchers diff --git a/lib/matchers.ts b/lib/matchers.ts index e2f5913..5b2a26f 100644 --- a/lib/matchers.ts +++ b/lib/matchers.ts @@ -3,6 +3,7 @@ import type { Term } from '@rdfjs/types' import type { AnyPointer } from 'clownface' import toNT from '@rdfjs/to-ntriples' import type deepEqual from 'deep-eql' +import env from '@zazuko/env-node' declare global { /* eslint-disable @typescript-eslint/no-namespace */ @@ -34,36 +35,16 @@ const plugin: Chai.ChaiPlugin = (_chai, util) => { ;['eq', 'equal', 'equals'].forEach((eq) => { Assertion.overwriteMethod(eq, function (_super) { - return function (this: any, other: Term) { + return function (this: any, other: AnyPointer | Term) { const obj: AnyPointer | Term | unknown = this._obj - if (isTermOrPointer(obj)) { - if ('terms' in obj) { - if (!obj.term) { - return this.assert( - false, - 'expected a pointer with single term #{exp} but got #{act} terms', - 'expected a pointer with single term not to equal #{exp}', - toNT(other), - obj.terms.length, - ) - } - - return this.assert( - other.equals(obj.term), - 'expected a pointer to #{exp} but got #{act}', - 'expected a pointer not to equal #{exp}', - toNT(other), - toNT(obj.term), - ) - } - + if (isTermOrPointer(obj) && isTermOrPointer(other)) { return this.assert( - other.equals(obj), - 'expected #{this} to equal #{exp}', - 'expected #{this} not to equal #{exp}', - toNT(other), - toNT(obj), + setEqual(getTerms(obj), getTerms(other)), + 'expected #{exp} but got #{act}', + 'expected #{act} not to equal #{exp}', + getDescription(other), + getDescription(obj), ) } @@ -77,4 +58,16 @@ function isTermOrPointer(value: T | unknown): value return typeof value === 'object' && value !== null && ('termType' in value || 'terms' in value) } +function getTerms(obj: AnyPointer | Term) { + return env.termSet('terms' in obj ? obj.terms : [obj]) +} + +function setEqual(left: Set, right: Set) { + return left.size === right.size && [...left].every((term) => right.has(term)) +} + +function getDescription(obj: AnyPointer | Term): string { + return 'terms' in obj ? `a pointer to ${obj.terms.map(toNT).join(', ')}` : toNT(obj) +} + export default plugin diff --git a/package-lock.json b/package-lock.json index 675f7f5..5220186 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mocha-chai-rdf", - "version": "0.1.1", + "version": "0.1.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mocha-chai-rdf", - "version": "0.1.1", + "version": "0.1.4", "license": "MIT", "dependencies": { "@rdfjs/to-ntriples": "^3.0.1", diff --git a/test/__snapshots__/index.test.ts.snap b/test/__snapshots__/index.test.ts.snap index bb5519a..dc492c0 100644 --- a/test/__snapshots__/index.test.ts.snap +++ b/test/__snapshots__/index.test.ts.snap @@ -34,9 +34,12 @@ exports[`mocha-chai-rdf test suites 3`] = ` ✔ matchers.js term when actual object is pointer succeeds when equal: 0ms 2) matchers.js term when actual object is pointer fails when not equal 3) matchers.js term when actual object is pointer fails when multi-pointer + ✔ matchers.js term when actual and expected objects are pointers succeeds when equal: 0ms + ✔ matchers.js term when actual and expected objects are pointers succeeds when equal multi-pointers: 0ms + 4) matchers.js term when actual and expected objects are pointers fails when not equal multi-pointers - 22 passing (0ms) - 3 failing + 24 passing (0ms) + 4 failing 1) store.js createStore @@ -60,10 +63,10 @@ exports[`mocha-chai-rdf test suites 3`] = ` when actual object is pointer fails when not equal: - AssertionError: expected a pointer to '\\"http://example.org/\\"' but got '' + AssertionError: expected '\\"http://example.org/\\"' but got 'a pointer to ' + expected - actual - - + -a pointer to +\\"http://example.org/\\" at Context. @@ -73,7 +76,27 @@ exports[`mocha-chai-rdf test suites 3`] = ` term when actual object is pointer fails when multi-pointer: - AssertionError: expected a pointer with single term '' but got 2 terms + + AssertionError: expected '' but got 'a pointer to , …' + + expected - actual + + -a pointer to , + + + + at Context. + at process.processImmediate + + 4) matchers.js + term + when actual and expected objects are pointers + fails when not equal multi-pointers: + + AssertionError: expected 'a pointer to , …' but got 'a pointer to , …' + + expected - actual + + -a pointer to , + +a pointer to , + at Context. at process.processImmediate diff --git a/test/tests/matchers.ts b/test/tests/matchers.ts index b830cb8..ab056c1 100644 --- a/test/tests/matchers.ts +++ b/test/tests/matchers.ts @@ -64,5 +64,46 @@ describe('matchers.js', () => { expect(pointer).to.be.eq(rdf.namedNode(iri)) }) }) + + context('when actual and expected objects are pointers', () => { + it('succeeds when equal', () => { + // given + const iri = 'http://example.org/' + const actual = rdf.clownface().node(oxigraph.namedNode(iri)) + const expected = rdf.clownface().node(rdf.namedNode(iri)) + + expect(actual).to.be.eq(expected) + }) + + it('succeeds when equal multi-pointers', () => { + // given + const iri = 'http://example.org/' + const actual = rdf.clownface().node([ + oxigraph.namedNode(iri + 1), + oxigraph.namedNode(iri + 2), + ]) + const expected = rdf.clownface().node([ + rdf.namedNode(iri + 1), + rdf.namedNode(iri + 2), + ]) + + expect(actual).to.be.eq(expected) + }) + + it('fails when not equal multi-pointers', () => { + // given + const iri = 'http://example.org/' + const actual = rdf.clownface().node([ + oxigraph.namedNode(iri + 1), + oxigraph.namedNode(iri + 2), + ]) + const expected = rdf.clownface().node([ + rdf.namedNode(iri + 1), + rdf.namedNode(iri + 3), + ]) + + expect(actual).to.be.eq(expected) + }) + }) }) })