Skip to content

Commit

Permalink
Merge pull request #30 from annarieger/getcombinedrequests-wfsfilterutil
Browse files Browse the repository at this point in the history
Add `getCombinedRequests` method to `WfsSearchUtil`
  • Loading branch information
annarieger committed Sep 17, 2018
2 parents ee1379f + 36f74ad commit fef1cc5
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 11 deletions.
5 changes: 4 additions & 1 deletion jest/setup.js
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
import 'whatwg-fetch';
import 'whatwg-fetch';
import { XMLSerializer } from 'xmldom';

global.XMLSerializer = XMLSerializer;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
"node-pre-gyp": "0.11.0",
"np": "3.0.4",
"ol": "5.2.0",
"whatwg-fetch": "2.0.4"
"whatwg-fetch": "2.0.4",
"xmldom": "0.1.27"
},
"peerDependencies": {
"ol": "~5.0"
Expand Down
76 changes: 76 additions & 0 deletions src/WfsFilterUtil/WfsFilterUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {
or
} from 'ol/format/filter';

import OlFormatWFS from 'ol/format/WFS';

/**
* Helper Class for building filters to be used with WFS GetFeature requests.
*
Expand Down Expand Up @@ -58,6 +60,80 @@ class WfsFilterUtil {
return propertyFilters[0];
}
}


/**
* Creates GetFeature request body for all provided featureTypes and
* applies related filter encoding on it.
*
* @param {Object} searchOpts. Search options object which has the following
* keys (see also https://github.com/terrestris/react-geo/blob/master/src/Field/WfsSearch/
* for further options explanations and examples):
* * featureNS {String} The namespace URI used for features
* * featurePrefix {String} The prefix for the feature namespace.
* * featureTypes {String[]} The feature type names to search through.
* * geometryName {String} Geometry name to use in a BBOX filter.
* * maxFeatures {Number} Maximum number of features to fetch.
* * outputFormat {String} The output format of the response.
* * propertyNames {String[]} Optional list of property names to serialize.
* * srsName {String} SRS name.
* * wfsFormatOptions {Object} Options which are passed to the constructor of the ol.format.WFS
* (compare: https://openlayers.org/en/latest/apidoc/ol.format.WFS.html)
* * searchAttributes {Object} An object mapping feature types to an array
* of attributes that should be searched through.
* * attributeDetails {Object} A nested object mapping feature types to an
* object of attribute details, which are also
* mapped by search attribute name.
* @param {String} searchTerm Search string to be used with filter.
*/
static getCombinedRequests(searchOpts, searchTerm) {

const {
featureNS,
featurePrefix,
featureTypes,
geometryName,
maxFeatures,
outputFormat,
propertyNames,
srsName,
wfsFormatOptions,
searchAttributes,
attributeDetails
} = searchOpts;

const requests = featureTypes.map(featureType => {

const filter = WfsFilterUtil.createWfsFilter(
featureType, searchTerm, searchAttributes, attributeDetails
);
const options = {
featureNS,
featurePrefix,
featureTypes: [featureType],
geometryName,
maxFeatures,
outputFormat,
propertyNames,
srsName,
filter: filter
};

const wfsFormat = new OlFormatWFS(wfsFormatOptions);
return wfsFormat.writeGetFeature(options);
});

const request = requests[0];

requests.forEach(req => {
if (req !== request) {
const query = req.querySelector('Query');
request.append(query);
}
});

return request;
}
}

export default WfsFilterUtil;
59 changes: 50 additions & 9 deletions src/WfsFilterUtil/WfsFilterUtil.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,17 @@ describe('WfsFilterUtil', () => {

describe('Static methods', () => {

afterEach(() => {
searchAttributes = {
'featureType': []
};
Object.keys(attributeDetails[featureType]).forEach(prop => {
delete attributeDetails[featureType][prop];
});
});

describe('#createWfsFilter', () => {

afterEach(() => {
searchAttributes = {
'featureType': []
};
Object.keys(attributeDetails[featureType]).forEach(prop => {
delete attributeDetails[featureType][prop];
});
});

it('is defined', () => {
expect(WfsFilterUtil.createWfsFilter).toBeDefined();
});
Expand Down Expand Up @@ -117,5 +117,46 @@ describe('WfsFilterUtil', () => {
expect(got.conditions.length).toEqual(searchAttributes[featureType].length);
});
});

describe('#getCombinedRequests', () => {

const searchOpts = {
featureTypes: [
'someNs:someFeatureType',
'someAnotherNs:someAnotherFeatureType'
],
'searchAttributes': {
'someNs:someFeatureType': [
'name'
],
'someAnotherNs:someAnotherFeatureType': [
'anotherName'
]
}
};
const searchTerm = 'findMe';

it('is defined', () => {
expect(WfsFilterUtil.getCombinedRequests).toBeDefined();
});

it('creates WFS filter for each feature type', () => {
const filterSpy = jest.spyOn(WfsFilterUtil, 'createWfsFilter');
WfsFilterUtil.getCombinedRequests(searchOpts, searchTerm);
expect(filterSpy).toHaveBeenCalledTimes(searchOpts.featureTypes.length);
filterSpy.mockReset();
filterSpy.mockRestore();
});

it('creates WFS GetFeature request body containing queries and filter for each feature type', () => {
const got = WfsFilterUtil.getCombinedRequests(searchOpts, searchTerm);
expect(got.tagName).toBe('GetFeature');
expect(got.querySelectorAll('Query').length).toBe(searchOpts.featureTypes.length);
got.querySelectorAll('Query').forEach(query => {
expect(query.children[0].tagName).toBe('Filter');
expect(query.children[0].getElementsByTagName('Literal')[0].innerHTML).toBe(`*${searchTerm}*`);
});
});
});
});
});

0 comments on commit fef1cc5

Please sign in to comment.