Skip to content

Commit 067a849

Browse files
add integration test
1 parent 4db7392 commit 067a849

File tree

8 files changed

+190
-18
lines changed

8 files changed

+190
-18
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,3 +411,7 @@ types/
411411

412412
# examples
413413
examples/package-lock.json
414+
415+
# cert
416+
*.cert
417+
*.key

package-lock.json

Lines changed: 57 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
"sinon": "^15.2.0",
5353
"tslib": "^2.6.0",
5454
"typescript": "^5.1.6",
55-
"uuid": "^9.0.1"
55+
"uuid": "^9.0.1",
56+
"selfsigned": "^2.4.1"
5657
},
5758
"dependencies": {
5859
"@azure/app-configuration": "^1.6.1",

src/AzureAppConfigurationImpl.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,6 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
258258
}
259259

260260
async #loadFeatureFlags() {
261-
this.#featureFlagTracing.resetFeatureFlagTracing();
262261
const featureFlagSettings: ConfigurationSetting[] = [];
263262
for (const selector of this.#featureFlagSelectors) {
264263
const listOptions: ListConfigurationSettingsOptions = {
@@ -283,6 +282,8 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
283282
selector.pageEtags = pageEtags;
284283
}
285284

285+
this.#featureFlagTracing.resetFeatureFlagTracing();
286+
286287
// parse feature flags
287288
const featureFlags = await Promise.all(
288289
featureFlagSettings.map(setting => this.#parseFeatureFlag(setting))

test/integration.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
import * as chai from "chai";
5+
import * as chaiAsPromised from "chai-as-promised";
6+
chai.use(chaiAsPromised);
7+
const expect = chai.expect;
8+
import { createMockedConnectionString, createMockedFeatureFlag, HttpRequestHeadersPolicy, sleepInMs } from "./utils/testHelper";
9+
import { mockServerEndpoint, startMockServer, closeMockServer } from "./utils/integrationTestHelper";
10+
import { load } from "./exportedApi";
11+
12+
describe("integration test", function () {
13+
this.timeout(15000);
14+
15+
const headerPolicy = new HttpRequestHeadersPolicy();
16+
const position: "perCall" | "perRetry" = "perCall";
17+
const clientOptions = {
18+
retryOptions: {
19+
maxRetries: 0 // save time
20+
},
21+
allowInsecureConnection: true,
22+
additionalPolicies: [{
23+
policy: headerPolicy,
24+
position
25+
}]
26+
};
27+
28+
it("should have request type in correlation-context header if feature flags use feature filters", async () => {
29+
// We are using self-signed certificate
30+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
31+
32+
startMockServer([
33+
createMockedFeatureFlag("Alpha_1", { conditions: { client_filters: [ { name: "Microsoft.TimeWindow" } ] } }),
34+
createMockedFeatureFlag("Alpha_2", { conditions: { client_filters: [ { name: "Microsoft.Targeting" } ] } }),
35+
createMockedFeatureFlag("Alpha_3", { conditions: { client_filters: [ { name: "CustomFilter" } ] } })
36+
]);
37+
38+
const settings = await load(createMockedConnectionString(mockServerEndpoint), {
39+
clientOptions,
40+
featureFlagOptions: {
41+
enabled: true,
42+
selectors: [ {keyFilter: "*"} ],
43+
refresh: {
44+
enabled: true,
45+
refreshIntervalInMs: 1000
46+
}
47+
}
48+
});
49+
await sleepInMs(1000 + 1);
50+
try {
51+
await settings.refresh();
52+
} catch (e) { /* empty */ }
53+
expect(headerPolicy.headers).not.undefined;
54+
const correlationContext = headerPolicy.headers.get("Correlation-Context");
55+
expect(correlationContext).not.undefined;
56+
expect(correlationContext.includes("RequestType=Watch")).eq(true);
57+
expect(correlationContext.includes("Filter=CSTM+TIME+TRGT")).eq(true);
58+
59+
closeMockServer();
60+
});
61+
});

test/requestTracing.test.ts

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,9 @@ import * as chai from "chai";
55
import * as chaiAsPromised from "chai-as-promised";
66
chai.use(chaiAsPromised);
77
const expect = chai.expect;
8-
import { createMockedConnectionString, createMockedKeyValue, createMockedTokenCredential, mockAppConfigurationClientListConfigurationSettings, restoreMocks, sleepInMs } from "./utils/testHelper";
8+
import { createMockedConnectionString, createMockedKeyValue, createMockedTokenCredential, mockAppConfigurationClientListConfigurationSettings, restoreMocks, HttpRequestHeadersPolicy, sleepInMs } from "./utils/testHelper";
99
import { load } from "./exportedApi";
1010

11-
class HttpRequestHeadersPolicy {
12-
headers: any;
13-
name: string;
14-
15-
constructor() {
16-
this.headers = {};
17-
this.name = "HttpRequestHeadersPolicy";
18-
}
19-
sendRequest(req, next) {
20-
this.headers = req.headers;
21-
return next(req).then(resp => resp);
22-
}
23-
}
24-
2511
describe("request tracing", function () {
2612
this.timeout(15000);
2713

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { ConfigurationSetting } from "@azure/app-configuration";
2+
import * as https from "https";
3+
import * as selfsigned from "selfsigned";
4+
import * as fs from "fs";
5+
6+
let server;
7+
8+
const domain = "localhost";
9+
const port = 443
10+
11+
function startMockServer(settings: ConfigurationSetting[]) {
12+
const attrs = [{ name: "commonName", value: domain }];
13+
const certOptions = { keySize: 2048, selfSigned: true };
14+
const pems = selfsigned.generate(attrs, certOptions);
15+
16+
fs.writeFileSync("server.key", pems.private);
17+
fs.writeFileSync("server.cert", pems.cert);
18+
19+
const options = {
20+
key: fs.readFileSync("server.key"),
21+
cert: fs.readFileSync("server.cert")
22+
};
23+
24+
const responseBody = {
25+
items: [...settings]
26+
};
27+
28+
server = https.createServer(options, (req, res) => {
29+
res.writeHead(200, { "Content-Type": "application/json" });
30+
res.end(JSON.stringify(responseBody));
31+
});
32+
33+
server.listen(port);
34+
}
35+
36+
function closeMockServer() {
37+
server.close();
38+
}
39+
40+
const mockServerEndpoint = "https://localhost:443";
41+
42+
export {
43+
startMockServer,
44+
closeMockServer,
45+
mockServerEndpoint
46+
}

test/utils/testHelper.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,20 @@ const createMockedFeatureFlag = (name: string, flagProps?: any, props?: any) =>
194194
isReadOnly: false
195195
}, props));
196196

197+
class HttpRequestHeadersPolicy {
198+
headers: any;
199+
name: string;
200+
201+
constructor() {
202+
this.headers = {};
203+
this.name = "HttpRequestHeadersPolicy";
204+
}
205+
sendRequest(req, next) {
206+
this.headers = req.headers;
207+
return next(req).then(resp => resp);
208+
}
209+
}
210+
197211
export {
198212
sinon,
199213
mockAppConfigurationClientListConfigurationSettings,
@@ -209,5 +223,7 @@ export {
209223
createMockedKeyValue,
210224
createMockedFeatureFlag,
211225

226+
HttpRequestHeadersPolicy,
227+
212228
sleepInMs
213-
};
229+
};

0 commit comments

Comments
 (0)