Skip to content

Commit

Permalink
Merge pull request #183 from Deltares/182-add-whatif-scenario-post-en…
Browse files Browse the repository at this point in the history
…dpoint

Add post what if endpoint
  • Loading branch information
hvangeffen authored Feb 10, 2025
2 parents cee35e3 + 4c6d404 commit 3dd4b7f
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 1 deletion.
4 changes: 4 additions & 0 deletions scripts/generateTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ const piCommands = [
url: `${config.url}/pi_rest_whatifscenariodescriptors.json`,
output: "src/response/embedded/whatIfScenarioDescriptorsResponse.ts",
},
{
url: `${config.url}/pi_rest_whatifscenariodescriptor.json`,
output: "src/response/embedded/whatIfScenarioDescriptorResponse.ts",
},
];

const archiveCommands = [
Expand Down
34 changes: 33 additions & 1 deletion src/piWebserviceProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import type {
DashboardsFilter,
WhatIfScenariosFilter,
WhatIfTemplatesFilter,
PostWhatIfScenarioFilter,
} from "./requestParameters";
import type {TopologyNodeResponse} from "./response/topology";
import type {TopologyActionFilter} from "./requestParameters/topologyActionFilter";
Expand All @@ -43,7 +44,7 @@ import {DocumentFormat} from './requestParameters/index.js'
import {HistoryEditsFilter} from "./requestParameters/historyEditsFilter";
import {HistoryEditsResponse} from "./response/timeseries/historyEditsResponse";

import {PiRestService, PlainTextParser, RequestOptions} from "@deltares/fews-web-oc-utils";
import {DefaultParser, PiRestService, PlainTextParser, RequestOptions} from "@deltares/fews-web-oc-utils";
import type {TransformRequestFunction} from "@deltares/fews-web-oc-utils";
import DataRequestResult from "@deltares/fews-web-oc-utils/lib/types/restservice/dataRequestResult";
import { TimeSeriesGridMaxValuesFilter } from './requestParameters/timeSeriesGridMaxValuesFilter'
Expand All @@ -54,6 +55,7 @@ import type { LogsDisplayLogsResponse } from './response/logs/logDisplayLogsResp
import type { LogsDisplaysResponse } from './response/logs/logDisplaysResponse'
import type { WhatIfTemplatesResponse } from './response/embedded/whatIfTemplatesResponse'
import type { WhatIfScenarioResponse } from './response/embedded/whatIfScenarioDescriptorsResponse'
import type { PostWhatIfScenarioResponse } from './response/embedded/whatIfScenarioDescriptorResponse'
import { WebOCDashboardsResponse } from './response/dashboards/webOcDashboardsResponse'

export class PiWebserviceProvider {
Expand Down Expand Up @@ -537,6 +539,27 @@ export class PiWebserviceProvider {
return res.data
}

/**
* Runs a what if scenario for a given whatIfTemplateId.
*
* @param filter an object with request query parameters
* @param piParametersXmlContent URL Encoded model parameters content that validates against the
* following xsd: https://fewsdocs.deltares.nl/schemas/version1.0/pi-schemas/pi_modelparameters.xsd
* @returns the WhatIfScenario of the submitted job.
* @throws 'Fetch Error' if fetch result is not ok
*/
async postWhatIfScenario(filter: PostWhatIfScenarioFilter, piParametersXmlContent: string): Promise<PostWhatIfScenarioResponse> {
const url = this.postWhatIfScenarioUrl(filter)
const requestOptions = new RequestOptions()
requestOptions.relativeUrl = !url.toString().startsWith("http")

const headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
const res = await this.webservice.postDataWithParser<PostWhatIfScenarioResponse>(url.toString(), requestOptions, new DefaultParser(), piParametersXmlContent, headers);
return res.data
}

/**
* Get the reporets for filter
*
Expand Down Expand Up @@ -930,4 +953,13 @@ export class PiWebserviceProvider {
this._baseUrl
)
}

postWhatIfScenarioUrl(filter: PostWhatIfScenarioFilter): URL {
const queryParameters = filterToParams(filter)
return new URL(
`${this._baseUrl.pathname}${this.API_ENDPOINT}/whatifscenario${queryParameters}`,
this._baseUrl
)
}

}
1 change: 1 addition & 0 deletions src/requestParameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ export * from './logDisplaysFilter.js'
export * from './logDisplayLogsFilter.js'
export * from './whatIfScenariosFilter.js'
export * from './whatIfTemplatesFilter.js'
export * from './postWhatIfScenarioFilter.js'
16 changes: 16 additions & 0 deletions src/requestParameters/postWhatIfScenarioFilter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export interface PostWhatIfScenarioFilter {
whatIfTemplateId: string;
name: string;

/**
* Since 2022.02. Properties can be included in the url. These will be used as
* taskRunProperties, and override global or workflow properties. Each property has to be added
* to the url seperately. Example:
*
* &property(fileName)=exportFile&property(outputValue)=9.0
*
* Where the name of the property is fileName, the value is exportFile. The name of the second
* property is outputValue, the value is 9.0.
*/
properties?: { [key: string]: string | number }
}
1 change: 1 addition & 0 deletions src/response/embedded/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './whatIfTemplatesResponse.js'
export * from './whatIfScenarioDescriptorsResponse.js'
export * from './whatIfScenarioDescriptorResponse.js'
8 changes: 8 additions & 0 deletions src/response/embedded/whatIfScenarioDescriptorResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* tslint:disable */

import { WhatIfScenarioDescriptor } from "./whatIfScenarioDescriptorsResponse";

/**
* WhatIfScenarioResponse PI_JSON
*/
export type PostWhatIfScenarioResponse = WhatIfScenarioDescriptor;
51 changes: 51 additions & 0 deletions test/unit/fews/postWhatIfScenario.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { PiWebserviceProvider } from "../../../src/piWebserviceProvider";
import "cross-fetch/polyfill";
import expectedResponse from "../mock/whatifscenario.json";
import fetchMock from "fetch-mock";
import { PostWhatIfScenarioFilter } from "../../../src/requestParameters/postWhatIfScenarioFilter";

describe("postWhatIfScenario", function () {
afterAll(function () {
fetchMock.restore();
});

it("generates a valid postWhatIfScenario request", async function () {
const baseUrl =
"https://mock.dev/fewswebservices/rest/fewspiservice/v1/whatifscenario";
const queryParams = `whatIfTemplateId=testid&name=test&property(ADD_SURGE)=0.2&property(MULTIPLY_SURGE)=1.3`;

const url = `${baseUrl}?${queryParams}`;

fetchMock.post(url, {
status: 200,
body: expectedResponse,
});

const provider = new PiWebserviceProvider(
"https://mock.dev/fewswebservices"
);

const properties = {
ADD_SURGE: 0.2,
MULTIPLY_SURGE: 1.3,
};

const filter: PostWhatIfScenarioFilter = {
whatIfTemplateId: "testid",
name: "test",
properties,
};
const results = await provider.postWhatIfScenario(filter, "");
expect(results).toStrictEqual(expectedResponse);
expect(results.id).toBe("id1");
expect(results.name).toBe("triple_the_surge");
expect(results.whatIfTemplateId).toBe("whatif_surge");
expect(results.properties?.length).toBe(2);
expect(results.properties?.[0].id).toBe("ADD_SURGE");
expect(results.properties?.[0].type).toBe("number");
expect(results.properties?.[0].value).toBe(0);
expect(results.properties?.[1].id).toBe("MULTIPLY_SURGE");
expect(results.properties?.[1].type).toBe("number");
expect(results.properties?.[1].value).toBe(3);
});
});
9 changes: 9 additions & 0 deletions test/unit/mock/whatifscenario.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"id": "id1",
"name": "triple_the_surge",
"whatIfTemplateId": "whatif_surge",
"properties": [
{ "id": "ADD_SURGE", "type": "number", "value": 0 },
{ "id": "MULTIPLY_SURGE", "type": "number", "value": 3 }
]
}

0 comments on commit 3dd4b7f

Please sign in to comment.