Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* Added getDefaultUrl helper in URLUtils.js
Fixed callers into urlUtils library, make sure a string is passed for the url argument.
FIxed impl which assumes that layer.url can only be string.

* Fix typo, actually fix the reported problem

* Added tests where getDefaultUrl change is introduced.

* Fixed multiple url test in styleeditor-test.js

* Added missing tests in WFS-test.js
Fixed license year in new files.
Adjusted styleeditor-test.js to more appropriately test the bugfix.

Tweaked wms dc.references in CSW.js to always default to a single URL string.
  • Loading branch information
Igi-ID authored Mar 26, 2024
1 parent 6c54526 commit c9eae7d
Show file tree
Hide file tree
Showing 20 changed files with 360 additions and 25 deletions.
9 changes: 5 additions & 4 deletions web/client/api/CSW.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import { cleanDuplicatedQuestionMarks } from '../utils/ConfigUtils';
import { extractCrsFromURN, makeBboxFromOWS, makeNumericEPSG, getExtentFromNormalized } from '../utils/CoordinatesUtils';
import WMS from "../api/WMS";
import { THREE_D_TILES, getCapabilities } from './ThreeDTiles';
import { getDefaultUrl } from '../utils/URLUtils';

const parseUrl = (url) => {
const parsed = urlUtil.parse(url, true);
export const parseUrl = (url) => {
const parsed = urlUtil.parse(getDefaultUrl(url), true);
return urlUtil.format(assign({}, parsed, { search: null }, {
query: assign({
service: "CSW",
Expand Down Expand Up @@ -170,9 +171,9 @@ export const getLayerReferenceFromDc = (dc, options, checkEsri = true) => {
const refs = castArray(dc.references);
const wms = head(refs.filter((ref) => { return ref.scheme && REGEX_WMS_EXPLICIT.some(regex => ref.scheme.match(regex)); }));
if (wms) {
let urlObj = urlUtil.parse(wms.value, true);
let urlObj = urlUtil.parse(getDefaultUrl(wms.value), true);
let layerName = urlObj.query && urlObj.query.layers || dc.alternative;
return toReference('wms', { ...wms, name: layerName }, options);
return toReference('wms', { ...wms, value: urlUtil.format(urlObj), name: layerName }, options);
}
if (checkEsri) {
// checks for esri arcgis in geonode csw
Expand Down
3 changes: 2 additions & 1 deletion web/client/api/WCS.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import axios from '../libs/ajax';
import urlUtil from 'url';
import assign from 'object-assign';
import xml2js from 'xml2js';
import { getDefaultUrl } from '../utils/URLUtils';

export const describeCoverage = function(url, typeName) {
const parsed = urlUtil.parse(url, true);
const parsed = urlUtil.parse(getDefaultUrl(url), true);
const describeLayerUrl = urlUtil.format(assign({}, parsed, {
query: assign({
service: "WCS",
Expand Down
9 changes: 5 additions & 4 deletions web/client/api/WFS.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import urlUtil from 'url';
import assign from 'object-assign';
import requestBuilder from '../utils/ogc/WFS/RequestBuilder';
import {toOGCFilterParts} from '../utils/FilterUtils';
import { getDefaultUrl } from '../utils/URLUtils';

export const toDescribeURL = (url, typeName) => {
const parsed = urlUtil.parse(url, true);
const parsed = urlUtil.parse(getDefaultUrl(url), true);
return urlUtil.format(
{
...parsed,
Expand Down Expand Up @@ -45,7 +46,7 @@ export const getFeatureSimple = function(baseUrl, params) {
};

export const getCapabilitiesURL = (url, {version = "1.1.0"} = {}) => {
const parsed = urlUtil.parse(url, true);
const parsed = urlUtil.parse(getDefaultUrl(url), true);
return urlUtil.format(assign({}, parsed, {
query: assign({
service: "WFS",
Expand All @@ -56,7 +57,7 @@ export const getCapabilitiesURL = (url, {version = "1.1.0"} = {}) => {
};

export const getFeatureURL = (url, typeName, { version = "1.1.0", ...params } = {}) => {
const parsed = urlUtil.parse(url, true);
const parsed = urlUtil.parse(getDefaultUrl(url), true);
return urlUtil.format(assign({}, parsed, {
query: assign({
service: "WFS",
Expand Down Expand Up @@ -130,7 +131,7 @@ export const getCapabilities = function(url) {
* @deprecated
*/
export const describeFeatureTypeOGCSchemas = function(url, typeName) {
const parsed = urlUtil.parse(url, true);
const parsed = urlUtil.parse(getDefaultUrl(url), true);
const describeLayerUrl = urlUtil.format(assign({}, parsed, {
query: assign({
service: "WFS",
Expand Down
5 changes: 3 additions & 2 deletions web/client/api/WMTS.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const capabilitiesCache = {};

import { castArray } from 'lodash';
import { getEPSGCode } from '../utils/CoordinatesUtils';
import { getDefaultUrl } from '../utils/URLUtils';

import {
getOperations,
Expand All @@ -25,8 +26,8 @@ import {
getDefaultFormat
} from '../utils/WMTSUtils';

const parseUrl = (url) => {
const parsed = urlUtil.parse(url, true);
export const parseUrl = (url) => {
const parsed = urlUtil.parse(getDefaultUrl(url), true);
return urlUtil.format(assign({}, parsed, {search: null}, {
query: assign({
SERVICE: "WMTS",
Expand Down
24 changes: 21 additions & 3 deletions web/client/api/__tests__/CSW-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import GRDCResponse from 'raw-loader!../../test-resources/csw/getRecordsResponse
import GRDCResponseWith3DLayersAt1st from 'raw-loader!../../test-resources/csw/getRecordsResponseDCWith3DLayersAt1st.xml';
import GRDCResponseWith3DLayersAtMiddle from 'raw-loader!../../test-resources/csw/getRecordsResponseDCWith3DLayersAtMiddle.xml';
import GRDCResponseWith3DLayersAtLast from 'raw-loader!../../test-resources/csw/getRecordsResponseDCWith3DLayersAtLast.xml';
import API, {constructXMLBody, getLayerReferenceFromDc } from '../CSW';
import API, {constructXMLBody, getLayerReferenceFromDc, parseUrl } from '../CSW';

import tileSetResponse from '../../test-resources/3dtiles/tileSetSample2.json';

Expand Down Expand Up @@ -424,14 +424,14 @@ describe("getLayerReferenceFromDc", () => {
const layerRef = getLayerReferenceFromDc(dc);
expect(layerRef.params.name).toBe('some_layer');
expect(layerRef.type).toBe('OGC:WMS');
expect(layerRef.url).toBe('http://wmsurl');
expect(layerRef.url).toBe('http://wmsurl/');
});
it("test layer reference with dc.references of scheme OGC:WMS-http-get-map", () => {
const dc = {references: [{value: "http://wmsurl", scheme: 'OGC:WMS-http-get-map'}, {value: "wfsurl", scheme: 'OGC:WFS'}], alternative: "some_layer"};
const layerRef = getLayerReferenceFromDc(dc);
expect(layerRef.params.name).toBe('some_layer');
expect(layerRef.type).toBe('OGC:WMS-http-get-map');
expect(layerRef.url).toBe('http://wmsurl');
expect(layerRef.url).toBe('http://wmsurl/');
});
it("test layer reference with dc.URI of scheme serviceType/ogc/wms and options", () => {
const dc = {URI: [{value: "wmsurl?service=wms&layers=some_layer&version=1.3.0", protocol: 'serviceType/ogc/wms'}, {value: "wfsurl", protocol: 'OGC:WFS'}]};
Expand Down Expand Up @@ -461,7 +461,25 @@ describe("getLayerReferenceFromDc", () => {
expect(layerRef.type).toBe('arcgis');
expect(layerRef.url).toBe('http://esri_url');
});
it('parseUrl', () => {
const _url = [
'http://gs-stable.geosolutionsgroup.com:443/geoserver1',
'http://gs-stable.geosolutionsgroup.com:443/geoserver2',
'http://gs-stable.geosolutionsgroup.com:443/geoserver3'
];

expect(parseUrl(_url).split('?')[0]).toBe(_url[0]);
});
it('getLayerReferenceFromDc ', () => {
const _url = [
'http://gs-stable.geosolutionsgroup.com:443/geoserver1',
'http://gs-stable.geosolutionsgroup.com:443/geoserver2',
'http://gs-stable.geosolutionsgroup.com:443/geoserver3'
];
const dc = {references: [{value: _url, scheme: 'OGC:WMS'}, {value: "wfsurl", scheme: 'OGC:WFS'}], alternative: "some_layer"};

expect(getLayerReferenceFromDc(dc).url).toBe(_url[0]);
});
});


80 changes: 80 additions & 0 deletions web/client/api/__tests__/WCS-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2024, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
import { describeCoverage } from '../WCS';
import axios from '../../libs/ajax';
import expect from 'expect';

import MockAdapter from "axios-mock-adapter";
let mockAxios;

let _xmlSample = `<wcs>
<enabled>true</enabled>
<name>WCS</name>
<title>Web Coverage Service</title>
<maintainer>http://geoserver.org/comm</maintainer>
<abstrct>This server implements the WCS specification 1.0 and 1.1.1, it's reference implementation of WCS 1.1.1. All layers published by this service are available on WMS also.
</abstrct>
<accessConstraints>NONE</accessConstraints>
<fees>NONE</fees>
<versions>
<org.geotools.util.Version>
<version>1.0.0</version>
</org.geotools.util.Version>
<org.geotools.util.Version>
<version>1.1.1</version>
</org.geotools.util.Version>
<org.geotools.util.Version>
<version>2.0.1</version>
</org.geotools.util.Version>
</versions>
<keywords>
<string>WCS</string>
<string>WMS</string>
<string>GEOSERVER</string>
</keywords>
<metadataLink>
<type>undef</type>
<about>http://geoserver.sourceforge.net/html/index.php</about>
<metadataType>other</metadataType>
</metadataLink>
<citeCompliant>false</citeCompliant>
<onlineResource>http://geoserver.org</onlineResource>
<schemaBaseURL>http://schemas.opengis.net</schemaBaseURL>
<verbose>false</verbose>
<gmlPrefixing>false</gmlPrefixing>
<latLon>false</latLon>
<maxInputMemory>0</maxInputMemory>
<maxOutputMemory>0</maxOutputMemory>
</wcs>`;

describe('Test WCS API', () => {
beforeEach(done => {
mockAxios = new MockAdapter(axios);
setTimeout(done);
});

afterEach(done => {
mockAxios.restore();
setTimeout(done);
});
it('describeCoverage', (done) => {
mockAxios.onGet().reply(200, _xmlSample);
describeCoverage([
'http://gs-stable.geosolutionsgroup.com:443/geoserver/services/wcs/settings',
'http://gs-stable.geosolutionsgroup.com:443/geoserver2/services/wcs/settings',
'http://gs-stable.geosolutionsgroup.com:443/geoserver3/services/wcs/settings'
], 'testName').then((result) => {
try {
expect(result).toExist();
done();
} catch (ex) {
done(ex);
}
});
});
});
32 changes: 31 additions & 1 deletion web/client/api/__tests__/WFS-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import expect from 'expect';
import MockAdapter from 'axios-mock-adapter';
import axios from '../../libs/ajax';
import {
getFeatureLayer
getFeatureLayer,
toDescribeURL,
getCapabilitiesURL,
getFeatureURL
} from '../WFS';

let mockAxios;
Expand Down Expand Up @@ -119,5 +122,32 @@ describe('Test WFS ogc API functions', () => {
});
});
});
it('toDescribeURL with URL array', () => {
const _url = [
'http://gs-stable.geosolutionsgroup.com:443/geoserver1',
'http://gs-stable.geosolutionsgroup.com:443/geoserver2',
'http://gs-stable.geosolutionsgroup.com:443/geoserver3'
];

expect(toDescribeURL(_url, 'testName').split('?')[0]).toBe(_url[0]);
});
it('getCapabilitiesURL with URL array', () => {
const _url = [
'http://gs-stable.geosolutionsgroup.com:443/geoserver1',
'http://gs-stable.geosolutionsgroup.com:443/geoserver2',
'http://gs-stable.geosolutionsgroup.com:443/geoserver3'
];

expect(getCapabilitiesURL(_url).split('?')[0]).toBe(_url[0]);
});
it('getFeatureURL with URL array', () => {
const _url = [
'http://gs-stable.geosolutionsgroup.com:443/geoserver1',
'http://gs-stable.geosolutionsgroup.com:443/geoserver2',
'http://gs-stable.geosolutionsgroup.com:443/geoserver3'
];

expect(getFeatureURL(_url).split('?')[0]).toBe(_url[0]);
});

});
11 changes: 10 additions & 1 deletion web/client/api/__tests__/WMTS-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import expect from 'expect';

import API, { getLayerTileMatrixSetsInfo } from '../WMTS';
import API, { getLayerTileMatrixSetsInfo, parseUrl } from '../WMTS';
import { getGetTileURL } from '../../utils/WMTSUtils';
import MockAdapter from 'axios-mock-adapter';
import axios from '../../libs/ajax';
Expand Down Expand Up @@ -250,4 +250,13 @@ describe('Test correctness of the WMTS APIs (mock axios)', () => {
})
.catch(done);
});
it('parseUrl', () => {
const _url = [
'http://gs-stable.geosolutionsgroup.com:443/geoserver1',
'http://gs-stable.geosolutionsgroup.com:443/geoserver2',
'http://gs-stable.geosolutionsgroup.com:443/geoserver3'
];

expect(parseUrl(_url).split('?')[0]).toBe(_url[0]);
});
});
61 changes: 61 additions & 0 deletions web/client/epics/__tests__/styleeditor-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1475,5 +1475,66 @@ describe('Test styleeditor epics, with mock axios', () => {
state);

});
it('test toggleStyleEditorEpic style service where layer url is array', (done) => {
mockAxios.onGet(/\/manifest/).reply(() => {
return [ 200, { about: { resource: [{ '@name': 'gt-css-2.16' }]} }];
});

mockAxios.onGet(/\/version/).reply(() => {
return [ 200, { about: { resource: [{ '@name': 'GeoServer', version: '2.16' }] } }];
});

mockAxios.onGet(/\/fonts/).reply(() => {
return [ 200, { fonts: ['Arial'] }];
});

const state = {
layers: {
flat: [
{
id: 'layerId',
name: 'layerWorkspace:layerName',
url: ['/geoserver1/', '/geoserver2/', '/geoserver3/']
}
],
selected: [
'layerId'
],
settings: {
options: {
opacity: 1
}
}
}
};

const NUMBER_OF_ACTIONS = 3;
const results = (actions) => {
try {
const service = actions.pop()?.service;

expect(service).toEqual({
baseUrl: state.layers.flat[0].url[0],
version: '2.16',
formats: [ 'css', 'sld' ],
availableUrls: [],
fonts: ['Arial'],
classificationMethods: {
vector: [ 'equalInterval', 'quantile', 'jenks' ],
raster: [ 'equalInterval', 'quantile', 'jenks' ]
}
});
} catch (e) {
done(e);
}
done();
};

testEpic(
toggleStyleEditorEpic,
NUMBER_OF_ACTIONS,
toggleStyleEditor(undefined, true),
results,
state);
});
});
3 changes: 2 additions & 1 deletion web/client/epics/styleeditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {
import { getSelectedLayer, layerSettingSelector } from '../selectors/layers';
import { generateTemporaryStyleId, generateStyleId, STYLE_OWNER_NAME, getNameParts, detectStyleCodeChanges } from '../utils/StyleEditorUtils';
import { updateStyleService } from '../api/StyleEditor';
import { getDefaultUrl } from '../utils/URLUtils';

/*
* Observable to get code of a style, it works only in edit status
Expand Down Expand Up @@ -258,7 +259,7 @@ export const toggleStyleEditorEpic = (action$, store) =>
return getAvailableStylesFromLayerCapabilities(layer);
}

const layerUrl = layer.url.split(geoserverName);
const layerUrl = getDefaultUrl(layer.url).split(geoserverName);
const baseUrl = `${layerUrl[0]}${geoserverName}`;
const lastStyleService = styleServiceSelector(state);

Expand Down
Loading

0 comments on commit c9eae7d

Please sign in to comment.