Skip to content
Merged
9 changes: 9 additions & 0 deletions sdk/test-utils/recorder-new/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

## 1.0.0 (Unreleased)

## 2021-12-27

- Allows passing `undefined` as keys in the sanitizer options so that devs don't have to add additional checks if a certain env variable exists in playback.
- Exports `delay`
- waits for expected time in record/live modes
- no-op in playback

[#19561](https://github.com/Azure/azure-sdk-for-js/pull/19561)

## 2021-12-17

- Refactoring the test proxy http clients for better clarity for the end users [#19446](https://github.com/Azure/azure-sdk-for-js/pull/19446)
Expand Down
1 change: 1 addition & 0 deletions sdk/test-utils/recorder-new/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export {
isRecordMode
} from "./utils/utils";
export { env } from "./utils/env";
export { delay } from "./utils/delay";
18 changes: 10 additions & 8 deletions sdk/test-utils/recorder-new/src/sanitizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
getTestMode,
ProxyToolSanitizers,
RecorderError,
RegexSanitizer,
sanitizerKeywordMapping,
SanitizerOptions
} from "./utils/utils";
Expand All @@ -14,7 +15,7 @@ import {
* Sanitizer class to handle communication with the proxy-tool relating to the sanitizers adding/resetting, etc.
*/
export class Sanitizer {
constructor(private url: string, private httpClient: HttpClient) {}
constructor(private url: string, private httpClient: HttpClient) { }
private recordingId: string | undefined;

setRecordingId(recordingId: string): void {
Expand Down Expand Up @@ -74,12 +75,13 @@ export class Sanitizer {
const replacers = options[prop];
if (replacers) {
return Promise.all(
replacers.map((replacer: unknown) =>
this.addSanitizer({
replacers.map((replacer: RegexSanitizer) => {
if (!replacer.regex) return;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we throw if it's undefined in live/record mode?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm, good idea

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only record mode

return this.addSanitizer({
sanitizer: sanitizerKeywordMapping[prop],
body: JSON.stringify(replacer)
})
)
})
);
} else return;
})
Expand Down Expand Up @@ -140,9 +142,10 @@ export class Sanitizer {
* - generalRegexSanitizer is applied for each of the parts with the real and fake values that are parsed
*/
async addConnectionStringSanitizer(
actualConnString: string,
actualConnString: string | undefined,
fakeConnString: string
): Promise<void> {
if (!actualConnString) return;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we throw if it's undefined in live/record mode?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done
only record mode**

// extract connection string parts and match call
const pairsMatched = getRealAndFakePairs(actualConnString, fakeConnString);
await this.addSanitizers({
Expand All @@ -160,9 +163,8 @@ export class Sanitizer {
body: string | undefined;
}): Promise<void> {
if (this.recordingId !== undefined) {
const uri = `${this.url}${paths.admin}${
options.sanitizer !== "Reset" ? paths.addSanitizer : paths.reset
}`;
const uri = `${this.url}${paths.admin}${options.sanitizer !== "Reset" ? paths.addSanitizer : paths.reset
}`;
const req = this._createRecordingRequest(uri);
if (options.sanitizer !== "Reset") {
req.headers.set("x-abstraction-identifier", options.sanitizer);
Expand Down
16 changes: 16 additions & 0 deletions sdk/test-utils/recorder-new/src/utils/delay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { isPlaybackMode } from "./utils";

/**
* Usage - `await delay(<milliseconds>)`
* This `delay` has no effect if the `TEST_MODE` is `"playback"`.
* If the `TEST_MODE` is not `"playback"`, `delay` is a wrapper for setTimeout that resolves a promise after t milliseconds.
*
* @param {number} milliseconds The number of milliseconds to be delayed.
* @returns {Promise<T>} Resolved promise

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return type needs update

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

*/
export function delay(milliseconds: number): Promise<void> | null {
return isPlaybackMode() ? null : new Promise((resolve) => setTimeout(resolve, milliseconds));
}
Comment thread
HarshaNalluru marked this conversation as resolved.
Outdated
16 changes: 13 additions & 3 deletions sdk/test-utils/recorder-new/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export interface RegexSanitizer {
/**
* A regex. Can be defined as a simple regex replace OR if groupForReplace is set, a subsitution operation.
*/
regex: string;
regex?: string;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it optional because it is not used in playback mode? if regex is optional, is value optional too?

@HarshaNalluru HarshaNalluru Dec 27, 2021

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only meant for convenience while writing the tests. If regex is undefined, the sanitizer won't be added.

For value, typically it is hard-coded and is a non-null value.
If it turned out to be undefined, it is most likely that the user is doing something wrong/unexpected, hence I didn't think of allowing that.

/**
* The capture group that needs to be operated upon. Do not set if you're invoking a simple replacement operation.
*/
Expand Down Expand Up @@ -149,7 +149,7 @@ interface ConnectionStringSanitizer {
/**
* Real connection string with all the secrets
*/
actualConnString: string;
actualConnString?: string;
/**
* Fake connection string - with all the parts of the connection string mapped to fake values
*/
Expand Down Expand Up @@ -181,7 +181,17 @@ export interface SanitizerOptions {
* Regardless, there are examples present in `recorder-new/test/testProxyTests.spec.ts`.
*/
bodyRegexSanitizers?: RegexSanitizer[];

/**
* This sanitizer offers regex update of a specific JTokenPath.
*
* EG: "TableName" within a json response body having its value replaced by whatever substitution is offered.
* This simply means that if you are attempting to replace a specific key wholesale, this sanitizer will be simpler
* than configuring a BodyRegexSanitizer that has to match against the full "KeyName": "Value" that is part of the json structure.
*
* Further reading is available [here](https://www.newtonsoft.com/json/help/html/SelectToken.htm#SelectTokenJSONPath).
*
* If the body is NOT a JSON object, this sanitizer will NOT be applied.
*/
bodyKeySanitizers?: BodyKeySanitizer[];
/**
* TODO
Expand Down
Loading