• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geosolutions-it / MapStore2 / 15022192473

14 May 2025 01:37PM UTC coverage: 76.899% (-0.09%) from 76.993%
15022192473

Pull #10515

github

web-flow
Merge 76310647b into d76ffd67a
Pull Request #10515: #10514 - FeatureEditor filter by geometric area

30971 of 48268 branches covered (64.16%)

27 of 42 new or added lines in 6 files covered. (64.29%)

532 existing lines in 55 files now uncovered.

38582 of 50172 relevant lines covered (76.9%)

35.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.74
/web/client/api/WFS.js
1
/**
2
 * Copyright 2016, GeoSolutions Sas.
3
 * All rights reserved.
4
 *
5
 * This source code is licensed under the BSD-style license found in the
6
 * LICENSE file in the root directory of this source tree.
7
 */
8
import axios from '../libs/ajax';
9
import urlUtil from 'url';
10
import assign from 'object-assign';
11
import xml2js from 'xml2js';
12
import ConfigUtils from '../utils/ConfigUtils';
13
import requestBuilder from '../utils/ogc/WFS/RequestBuilder';
14
import {toOGCFilterParts} from '../utils/FilterUtils';
15
import { getDefaultUrl } from '../utils/URLUtils';
16
import { castArray } from 'lodash';
17
import { isValidGetFeatureInfoFormat } from '../utils/WMSUtils';
18
import { getAuthorizationBasic } from '../utils/SecurityUtils';
19

20
const capabilitiesCache = {};
1✔
21

22
export const toDescribeURL = (url, typeName) => {
1✔
23
    const parsed = urlUtil.parse(getDefaultUrl(url), true);
6✔
24
    return urlUtil.format(
6✔
25
        {
26
            ...parsed,
27
            search: undefined, // this allows to merge parameters correctly
28
            query: {
29
                ...parsed.query,
30

31
                service: "WFS",
32
                version: "1.1.0",
33
                typeName,
34
                outputFormat: 'application/json',
35
                request: "DescribeFeatureType"
36
            }
37
        });
38
};
39
/**
40
 * Simple getFeature using http GET method with json format
41
 */
42
export const getFeatureSimple = function(baseUrl, params) {
1✔
43
    return axios.get(baseUrl + '?service=WFS&version=1.1.0&request=GetFeature', {
21✔
44
        params: assign({
45
            outputFormat: "application/json"
46
        }, params)
47
    }).then((response) => {
48
        if (typeof response.data !== 'object') {
20!
UNCOV
49
            return JSON.parse(response.data);
×
50
        }
51
        return response.data;
20✔
52
    });
53
};
54

55
export const getCapabilitiesURL = (url, {version = "1.1.0"} = {}) => {
1✔
56
    const parsed = urlUtil.parse(getDefaultUrl(url), true);
7✔
57
    return urlUtil.format(assign({}, parsed, {
7✔
58
        search: undefined, // this allows to merge parameters correctly
59
        query: assign({
60
            version,
61
            ...parsed.query,
62
            service: "WFS",
63
            request: "GetCapabilities"
64
        })
65
    }));
66
};
67

68
export const getFeatureURL = (url, typeName, { version = "1.1.0", ...params } = {}) => {
1✔
69
    const parsed = urlUtil.parse(getDefaultUrl(url), true);
19✔
70
    return urlUtil.format(assign({}, parsed, {
19✔
71
        search: undefined, // this allows to merge parameters correctly
72
        query: assign({
73
            typeName,
74
            version,
75
            ...parsed.query,
76
            service: "WFS",
77
            request: "GetFeature",
78
            ...params
79
        })
80
    }));
81
};
82
/**
83
 * Performs a getFeature request (using axios POST) to a WFS service for a given MapStore layer WFS layer object.
84
 * @param {object} layer MapStore layer object
85
 * @param {object} requestOptions additional request options. Can include:
86
 * - `version`: WFS version. Default: `1.1.0`
87
 * - `filter`: optional array of mapstore filters. If the layer has a `layerFilter` property or filterObj, it will be added to the filter in a logic AND.
88
 * - `proj`: projection string
89
 * - `outputFormat`: output format string. Default: `application/json`
90
 * - `resultType`: result type string. Default: `results`
91
 * @param {object} config axios request config (headers, etc...)
92
 */
93
export const getFeatureLayer = (layer, {version =  "1.1.0", filters, proj, outputFormat = 'application/json', resultType = 'results'} = {}, config) => {
1✔
94
    const {url, name: typeName, params } = layer;
7✔
95
    const {layerFilter, filterObj: featureGridFilter} = layer; // TODO: add
7✔
96
    const {getFeature: wfsGetFeature, query, filter, and} = requestBuilder({wfsVersion: version});
7✔
97
    const allFilters = []
7✔
98
        .concat(filters ?? [])
9✔
99
        .concat(layerFilter ? layerFilter : [])
7✔
100
        .concat(featureGridFilter ? featureGridFilter : []);
7!
101
    const reqBody = wfsGetFeature(query(
7✔
102
        typeName,
103
        // TODO: insert propertyName before filter to limit attributes to return
104
        allFilters.length > 0
7✔
105
            ? filter(
106
                and(
107
                    allFilters
108
                        .map(f => toOGCFilterParts(f, version, "ogc"))
6✔
109
                )
110

111
            ) : "",
112
        {srsName: proj} // 3rd for query is optional
113
    ),
114
    {outputFormat, resultType}
115
    );
116
    return axios.post(url, reqBody, {
7✔
117
        ...config,
118
        params,
119
        headers: {
120
            ...config?.headers,
121
            'Content-Type': 'application/xml'
122
        }
123
    });
124
};
125

126
/**
127
 * Performs a WFS GetFeature request (using axios GET) with the given parameters.
128
 * @param {string} url URL of the WFS service
129
 * @param {string} typeName layer name
130
 * @param {object} params the params to add to the request
131
 * @param {object} config axios request config (headers, etc...)
132
 * @returns {Promise} the axios promise
133
 */
134
export const getFeature = (url, typeName, params, config) => {
1✔
135
    return axios.get(getFeatureURL(url, typeName, params), config);
16✔
136
};
137

138
export const getCapabilities = function(url, info) {
1✔
139
    const cached = capabilitiesCache[url];
8✔
140
    if (cached && new Date().getTime() < cached.timestamp + (ConfigUtils.getConfigProp('cacheExpire') || 60) * 1000) {
8✔
141
        return Promise.resolve(cached.data);
2✔
142
    }
143
    const protectedId = info?.options?.service?.protectedId;
6✔
144
    let headers = getAuthorizationBasic(protectedId);
6✔
145
    return axios.get(getCapabilitiesURL(url, {headers}))
6✔
146
        .then((response) => {
147
            let json;
148
            xml2js.parseString(response.data, { explicitArray: false, stripPrefix: true }, (ignore, result) => {
5✔
149
                json = { ...result, url };
5✔
150
            });
151
            capabilitiesCache[url] = {
5✔
152
                timestamp: new Date().getTime(),
153
                data: json
154
            };
155
            return json;
5✔
156
        });
157
};
158

159
export const describeFeatureType = function(url, typeName) {
1✔
160
    return axios.get(toDescribeURL(url, typeName)).then(({data}) => data);
5✔
161
};
162

163
/**
164
 * Fetch the supported formats of the WFS service
165
 * @param url
166
 * @return {object} { infoFormats }
167
 */
168
export const getSupportedFormat = (url) => {
1✔
169
    return getCapabilities(url)
3✔
170
        .then((response) => {
171
            const operations = castArray(response?.['wfs:WFS_Capabilities']?.['ows:OperationsMetadata']?.['ows:Operation'] || []);
3✔
172
            const getFeatureOperation = operations.find(operation => operation?.$?.name === 'GetFeature');
3✔
173
            const parameters = castArray(getFeatureOperation?.['ows:Parameter'] || []);
3✔
174
            const outputFormats = parameters.find((parameter) => parameter?.$?.name === 'outputFormat')?.['ows:Value'] || [];
3✔
175
            const infoFormats = outputFormats.filter(isValidGetFeatureInfoFormat);
3✔
176
            return {
3✔
177
                infoFormats: infoFormats?.length ? infoFormats : ['application/json']
3✔
178
            };
179
        })
UNCOV
180
        .catch(() => ({ infoFormats: ['application/json'] }));
×
181
};
182

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc