Skip to content

Commit

Permalink
feat: Handle zero iterator results (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
ddeboer authored Jul 31, 2024
1 parent c526fbc commit feeb1d0
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 23 deletions.
8 changes: 4 additions & 4 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ export default {
coverageReporters: ['json-summary', 'text'],
coverageThreshold: {
global: {
lines: 70.65,
statements: 70.77,
branches: 66.66,
functions: 76.05,
lines: 71.03,
statements: 71.14,
branches: 67,
functions: 76.76,
},
},
transform: {
Expand Down
4 changes: 3 additions & 1 deletion src/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ export default class Generator extends EventEmitter<Events> {
}

private async flush(): Promise<void> {
await this.runBatch(this.$thisList);
if (this.$thisList.length > 0) {
await this.runBatch(this.$thisList);
}
}
}

Expand Down
10 changes: 9 additions & 1 deletion src/iterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default class Iterator extends EventEmitter<Events> {
const error = (e: unknown): Error =>
new Error(
`The Iterator did not run successfully, it could not get the results from the endpoint ${
this.source
this.source?.value
} (offset: ${this.offset}, limit ${this.query.limit}): ${
(e as Error).message
}`
Expand All @@ -62,6 +62,14 @@ export default class Iterator extends EventEmitter<Events> {
});
stream.on('end', () => {
this.totalResults += resultsPerPage;
if (this.totalResults === 0) {
this.emit(
'error',
error(
new Error(`no results for query:\n ${this.query.toString()}`)
)
);
}
this.offset += this.query.limit;
if (resultsPerPage < this.query.limit!) {
this.emit('end', this.totalResults);
Expand Down
55 changes: 38 additions & 17 deletions test/iterator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import removeDirectory from '../src/utils/removeDir.js';
import {NamedNode} from '@rdfjs/types';
import getSPARQLQuery from '../src/utils/getSPARQLQuery.js';
import getEndpoint from '../src/utils/getEndpoint.js';
import File from '../src/file.js';
chai.use(chaiAsPromised);

describe('Iterator Class', () => {
Expand Down Expand Up @@ -111,24 +112,9 @@ describe('Iterator Class', () => {
Query.from(getSPARQLQuery(stageConfig.iterator.query, 'select')),
getEndpoint(new Stage(pipeline, stageConfig))
);
const emittedEvents: {event: string; bindings?: NamedNode}[] = [];
async function runIteratorWithPromise(): Promise<boolean> {
return new Promise((resolve, reject) => {
iterator.addListener('data', bindings => {
emittedEvents.push({event: 'data', bindings});
});
iterator.addListener('end', () => {
emittedEvents.push({event: 'end'});
resolve(true);
});
iterator.addListener('error', error => {
reject(error);
});
iterator.run();
});
}

await runIteratorWithPromise();
const emittedEvents = await runIterator(iterator);

chai.expect(emittedEvents).to.have.lengthOf(154);
chai.expect(emittedEvents[0].event).to.equal('data');
chai.expect(emittedEvents[0].bindings?.termType).to.equal('NamedNode');
Expand All @@ -139,6 +125,22 @@ describe('Iterator Class', () => {
.expect(emittedEvents[emittedEvents.length - 1].event)
.to.equal('end');
});

it('throws error if query returns no results', async () => {
const query = Query.from(
getSPARQLQuery(
'SELECT $this WHERE { $this a <http://example.com/no-matches> }',
'select'
)
);
const iterator = new Iterator(
query,
new File('file://static/tests/iris-small.nt')
);
await expect(async () => await runIterator(iterator)).rejects.toThrow(
'no results for query:\n SELECT ?this WHERE { ?this <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.com/no-matches>. }'
);
});
});
});

Expand Down Expand Up @@ -175,3 +177,22 @@ describe('Query', () => {
);
});
});

async function runIterator(
iterator: Iterator
): Promise<{event: string; bindings?: NamedNode}[]> {
const emittedEvents: {event: string; bindings?: NamedNode}[] = [];
return new Promise((resolve, reject) => {
iterator.on('data', bindings => {
emittedEvents.push({event: 'data', bindings});
});
iterator.on('end', () => {
emittedEvents.push({event: 'end'});
resolve(emittedEvents);
});
iterator.on('error', error => {
reject(error);
});
iterator.run();
});
}

0 comments on commit feeb1d0

Please sign in to comment.