Skip to content

Data Connect: Add support for web framework tracking via custom headers #8749

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Feb 5, 2025
Merged
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
cdf7b39
add custom headers to track web frameworks usage
stephenarosaj Jan 28, 2025
fb27687
add transport methods to update framework usage flags after transport…
stephenarosaj Jan 30, 2025
6f27cbd
add transport methods to update framework usage flags after transport…
stephenarosaj Jan 30, 2025
40a8c0b
redesign framework/gen flags into CallerSdkType enum
stephenarosaj Jan 31, 2025
5e397d0
update custom headers assignment logic and values; add gen flag funct…
stephenarosaj Jan 31, 2025
1d504bf
unfreeze CallerSdkTypeEnum
stephenarosaj Jan 31, 2025
f45b282
add checking of _isUsingGen back to custom headers logic
stephenarosaj Jan 31, 2025
b307ae5
add call to _setCallerSdkType() on transport class
stephenarosaj Feb 4, 2025
112a605
add tests for fetch with custom headers based on dcFetch _callerSdkTy…
stephenarosaj Feb 4, 2025
7755617
add changeset for PR
stephenarosaj Feb 4, 2025
aa56521
flip header assignment logic to only use js/gen if _callerSdkType not…
stephenarosaj Feb 4, 2025
3339fde
add test for custom header values when _isUsingGen is true
stephenarosaj Feb 4, 2025
b77ad49
add firebase minor version bump to changeset
stephenarosaj Feb 4, 2025
2619098
fix formatting issues
stephenarosaj Feb 4, 2025
1e3db01
update changelog
stephenarosaj Feb 4, 2025
08accc6
only call transport's _setCallerSdkType() if DataConnect is initialized
stephenarosaj Feb 4, 2025
784597c
simplify tests
stephenarosaj Feb 4, 2025
9efd040
add comments explaining funky eslint logic
stephenarosaj Feb 5, 2025
595fee3
remove new, useless @internal comments
stephenarosaj Feb 5, 2025
99cced0
convert regex strings to regex literals
stephenarosaj Feb 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
simplify tests
  • Loading branch information
stephenarosaj committed Feb 4, 2025
commit 784597c340629160d635e8edfba4a01a6bab1cce
108 changes: 36 additions & 72 deletions packages/data-connect/test/unit/fetch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,48 +113,25 @@
false, // _isUsingGen is false
callerSdkType as CallerSdkType
);
}
}

// an example of the args to fetch():
// [
// "http://localhost",
// {
// "body": "{\"name\":\"n\",\"operationName\":\"n\",\"variables\":{}}",
// "headers": {
// "Content-Type": "application/json",
// "X-Goog-Api-Client": "gl-js/ fire/11.2.0"
// },
// "method": "POST",
// "signal": [undefined]
// }
// ]
for (let i = 0; i < fakeFetchImpl.args.length; i++) {
const args = fakeFetchImpl.args[i];
expect(args.length).to.equal(2);
expect(Object.prototype.hasOwnProperty.call(args[1], 'headers')).to.be
.true;
expect(
Object.prototype.hasOwnProperty.call(
args[1]['headers'],
'X-Goog-Api-Client'
)
).to.be.true;
expect(typeof args[1]['headers']['X-Goog-Api-Client']).to.equal('string');

const xGoogApiClientValue: string =
args[1]['headers']['X-Goog-Api-Client'];
// the sdk type headers are always of the form "js/xxx", where xxx is _callerSdkType.toLower()
// when the _callerSdkType is Base, we do not set any header
// when the _callerSdkType is Generated, we use "js/gen" instead of "js/generated"
if (callerSdkTypesUsed[i] === CallerSdkTypeEnum.Base) {
expect(xGoogApiClientValue).to.not.match(RegExp(`js\/w`));
} else if (callerSdkTypesUsed[i] === CallerSdkTypeEnum.Generated) {
expect(xGoogApiClientValue).to.match(RegExp(`js\/gen`));
} else {
expect(xGoogApiClientValue).to.match(
RegExp(`js\/${callerSdkTypesUsed[i].toLowerCase()}`)
);
let expectedHeaderRegex: RegExp;
if (callerSdkType === CallerSdkTypeEnum.Base) {
// should not contain any "js/xxx" substring
expectedHeaderRegex = RegExp(`^((?!js\/\w).)*$`);
} else if (callerSdkType === CallerSdkTypeEnum.Generated) {
expectedHeaderRegex = RegExp(`js\/gen`);
} else {
expectedHeaderRegex = RegExp(`js\/${callerSdkType.toLowerCase()}`);
}
expect(
fakeFetchImpl.calledWithMatch(
'http://localhost',
sinon.match.hasNested(
'headers.X-Goog-Api-Client',
sinon.match(expectedHeaderRegex)
)
)
).to.be.true;
}
}
});
Expand All @@ -165,13 +142,10 @@
};
const fakeFetchImpl = mockFetch(json, false);

const callerSdkTypesUsed: string[] = [];

for (const callerSdkType in CallerSdkTypeEnum) {
if (
Object.prototype.hasOwnProperty.call(CallerSdkTypeEnum, callerSdkType)
) {
callerSdkTypesUsed.push(callerSdkType);
await dcFetch(
'http://localhost',
{
Expand All @@ -186,35 +160,25 @@
true, // _isUsingGen is true
callerSdkType as CallerSdkType
);
}
}

for (let i = 0; i < fakeFetchImpl.args.length; i++) {
const args = fakeFetchImpl.args[i];
expect(args.length).to.equal(2);
expect(Object.prototype.hasOwnProperty.call(args[1], 'headers')).to.be
.true;
expect(
Object.prototype.hasOwnProperty.call(
args[1]['headers'],
'X-Goog-Api-Client'
)
).to.be.true;
expect(typeof args[1]['headers']['X-Goog-Api-Client']).to.equal('string');

const xGoogApiClientValue: string =
args[1]['headers']['X-Goog-Api-Client'];
// despite _isUsingGen being true, the headers should be based on _callerSdkType
// _isUsingGen should only take precedence when _callerSdkType is "Base"
if (
callerSdkTypesUsed[i] === CallerSdkTypeEnum.Generated ||
callerSdkTypesUsed[i] === CallerSdkTypeEnum.Base
) {
expect(xGoogApiClientValue).to.match(RegExp(`js\/gen`));
} else {
expect(xGoogApiClientValue).to.match(
RegExp(`js\/${callerSdkTypesUsed[i].toLowerCase()}`)
);
let expectedHeaderRegex: RegExp;
if (
callerSdkType === CallerSdkTypeEnum.Generated ||
callerSdkType === CallerSdkTypeEnum.Base
) {
expectedHeaderRegex = RegExp(`js\/gen`);
} else {
expectedHeaderRegex = RegExp(`js\/${callerSdkType.toLowerCase()}`);
}
expect(
fakeFetchImpl.calledWithMatch(
'http://localhost',
sinon.match.hasNested(
'headers.X-Goog-Api-Client',
sinon.match(expectedHeaderRegex)
)
)
).to.be.true;
}
}
});
Expand Down
Loading