Skip to content
This repository was archived by the owner on Nov 18, 2025. It is now read-only.

refactor: Use GoogleAuth#fetch and Fix Tests#1766

Merged
leahecole merged 16 commits intomainfrom
fix-gax-tests
Jun 6, 2025
Merged

refactor: Use GoogleAuth#fetch and Fix Tests#1766
leahecole merged 16 commits intomainfrom
fix-gax-tests

Conversation

@d-goog
Copy link
Contributor

@d-goog d-goog commented Jun 3, 2025

Description

This PR aims to:

  • resolve all silently failing tests*
  • fix tests that are misconfigured
  • establish improved patterns that will:
    • increase test reliability
    • improve maintainability
    • improve test performance

Using GoogleAuth#fetch streamlines allows us to streamline the code and simplify the unit tests as we can use a native Response object.

*system-tests are not included and are still flaky.

Impact

In addition to the above, as a side-effect we no longer need to directly import node-fetch within this library. We can remove in a separate PR.

Testing

Lots of testing improvements.

Additional Information

  • Note: While a large PR there is minimal change to gax/src/
  • This PR reduces our usage of proxyquire, which won't be supported in an ESM future, along with building improved patterns around using mock data with real data types (without casting).
  • nock raises an AbortController error when ran due to our overwriting the native AbortController. Fortunately, the GoogleAuth#fetch/Response route is more performant, however we shouldn't modify/replace native objects (anti-pattern).

BEGIN_COMMIT_OVERRIDE
fix: passing gaxios fetch through auth
END_COMMIT_OVERRIDE

Fixes: googleapis/google-cloud-node-core#182 🦕

@d-goog d-goog requested a review from a team June 3, 2025 04:37
@d-goog d-goog requested a review from a team as a code owner June 3, 2025 04:37
@product-auto-label product-auto-label bot added the size: xl Pull request size is extra large. label Jun 3, 2025
Comment on lines 163 to +164
auth
.getRequestHeaders()
.then(authHeader => {
const fetchRequest: RequestInit = {
headers: gaxios.Gaxios.mergeHeaders(authHeader, headers) as {},
body: fetchParameters.body as string | Buffer | undefined,
method: fetchParameters.method,
signal: cancelSignal,
};
if (agentOption) {
fetchRequest.agent = agentOption;
}
if (
fetchParameters.method === 'GET' ||
fetchParameters.method === 'DELETE'
) {
delete fetchRequest['body'];
}
return fetch(url, fetchRequest as {});
})
.fetch(url, fetchRequest)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using GoogleAuth#fetch to streamline and improve mocking options.

}
const apiCall = createApiCall(func);
await apiCall(42, undefined, (err, resp) => {
void apiCall(42, undefined, (err, resp) => {
Copy link
Contributor Author

@d-goog d-goog Jun 3, 2025

Choose a reason for hiding this comment

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

Used void to signal that this is a promise we intend to handle in floating async manner. The stubs by default are not compatible with traditional async/await patterns.

assert.ok(deadlineArg);
done();
})
.catch(done);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This .catch(done) will allow the test to fail faster than using .catch(console.error);

Copy link
Contributor

Choose a reason for hiding this comment

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

does this also need the void like the other tests?

re catch, great, love a faster fail

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question - the ones with the .catch(done) don't require the void as the .catch handles the floating async lint warning

Comment on lines +281 to +284
setMockFallbackResponse(
gaxGrpc,
new Response(Buffer.from(JSON.stringify(response))),
);
Copy link
Contributor Author

@d-goog d-goog Jun 3, 2025

Choose a reason for hiding this comment

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

This new utility makes it easier and simple to mock responses using the native Response object. Notice there are no fake mocks and no casting - just real data types which makes this easier to maintain.

const gaxGrpcMock = new GrpcClient();
setMockFallbackResponse(
gaxGrpc,
new Response(Buffer.from(JSON.stringify(jsonError)), {status: 400}),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

...it even supports errors in a simple way

Copy link
Contributor

@leahecole leahecole left a comment

Choose a reason for hiding this comment

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

it seems like there's a few things going on in this PR:

  • there's the work that was done to fix the fallback tests
  • there's also additional work - changing the browser tests
  • and the majority of these changes are updates to many of the unit tests and how we handle the async nature of them

The browser test changes are small, and given that they have some relevance to fetch + fallback from the linked issue, I would be okay grouping those in the PR, but I feel strongly that the other unit tests changes should be put in a separate PR (that I'm happy to review!)

assert.ok(deadlineArg);
done();
})
.catch(done);
Copy link
Contributor

Choose a reason for hiding this comment

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

does this also need the void like the other tests?

re catch, great, love a faster fail

@d-goog d-goog changed the title feat: Use GoogleAuth#fetch and Fix Tests refactor: Use GoogleAuth#fetch and Fix Tests Jun 3, 2025
@d-goog d-goog requested a review from leahecole June 4, 2025 16:55
Copy link
Contributor

@leahecole leahecole left a comment

Choose a reason for hiding this comment

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

Thanks for the some of the fixes to these comments! This PR still needs to be split up into multiple PRs that represent the discrete aspects of what is going on (fixing the fallback stuff, fixing the timing stuff, and potentially having the browser tests as a small third)- this will not only make it so #1737 is fixed faster (which means work on BigQuery modernization will be unblocked and has positive business impact! yay!) but having smaller PRs is safer in the unfortunate event that we did need to roll back a PR.

@d-goog
Copy link
Contributor Author

d-goog commented Jun 4, 2025

Thanks for the some of the fixes to these comments! This PR still needs to be split up into multiple PRs that represent the discrete aspects of what is going on (fixing the fallback stuff, fixing the timing stuff, and potentially having the browser tests as a small third)- this will not only make it so googleapis/google-cloud-node-core#182 is fixed faster (which means work on BigQuery modernization will be unblocked and has positive business impact! yay!) but having smaller PRs is safer in the unfortunate event that we did need to roll back a PR.

As mentioned here, we will need the browser changes in the PR. To further expand:

  • Many tests were broken or at risk for breaking due to the async issues/swallowing of the unit tests
  • I've looked into alternatives, such as adopting nock, however those won't work without a large refactor as well (larger than this PR)
    • For the nock case, adopting it caused tests to fail because of the way we mock AbortController (a global, btw), and fixing that would be larger
  • I've landed on using GoogleAuth#fetch since that would things up in the last amount of work (still a lot) and would allow us to use better practices going forward
    • These changes remove node-fetch usage, which we were mocking, thus the browser tests needed updating as well

To expedite this I would be happy to provide a walkthrough of these changes.

@d-goog d-goog requested a review from leahecole June 4, 2025 22:11
@leahecole
Copy link
Contributor

As mentioned here, we will need the browser changes in the PR.

I am willing to leave them in this PR, this is fine.

  • Many tests were broken or at risk for breaking due to the async issues/swallowing of the unit tests

Understood - however, linked issue googleapis/google-cloud-node-core#182 issue specifically calls out the grpc-fallback tests - I think that fixing all of the async issues and tests is valid, but needs to be split into two PRs:

  1. One that specifically deals with the refactoring to use GoogleAuth#fetch (which I believe is the fix for the grpc-fallback stuff) - this may include some more tests than just the fallback ones - it'll be the ones that used proxyquire before and things that pertain to fallback in general (quickly going through the files, I think that there's also some in the regapic.ts unit test file that would logically be goruped with this as well.) This one can also have the browser tests, since it kind of has to do with fetch too.
  2. One that handles the timing changes that are separate from this, but still need to be fixed - basically all of the unit tests where awaits were changed to voids and the .catchs were modified to fail faster - files including, but not limited to, apiCallable.ts and bundling.ts, locationService.ts, longrunning.ts, etc.
  • I've looked into alternatives, such as adopting nock, however those won't work without a large refactor as well (larger than this PR)

    • For the nock case, adopting it caused tests to fail because of the way we mock AbortController (a global, btw), and fixing that would be larger
  • I've landed on using GoogleAuth#fetch since that would things up in the last amount of work (still a lot) and would allow us to use better practices going forward

Understood, this makes sense. I think this is a reasonable alternative and a good choice given the circumstances. No issues with this choice.

  • These changes remove node-fetch usage, which we were mocking, thus the browser tests needed updating as well

To expedite this I would be happy to provide a walkthrough of these changes.

I appreciate the offer, but am happy to async review both PRs when this has been split up!

@d-goog
Copy link
Contributor Author

d-goog commented Jun 5, 2025

As mentioned here, we will need the browser changes in the PR.

I am willing to leave them in this PR, this is fine.

  • Many tests were broken or at risk for breaking due to the async issues/swallowing of the unit tests

Understood - however, linked issue googleapis/google-cloud-node-core#182 issue specifically calls out the grpc-fallback tests - I think that fixing all of the async issues and tests is valid, but needs to be split into two PRs:

  1. One that specifically deals with the refactoring to use GoogleAuth#fetch (which I believe is the fix for the grpc-fallback stuff) - this may include some more tests than just the fallback ones - it'll be the ones that used proxyquire before and things that pertain to fallback in general (quickly going through the files, I think that there's also some in the regapic.ts unit test file that would logically be goruped with this as well.) This one can also have the browser tests, since it kind of has to do with fetch too.
  2. One that handles the timing changes that are separate from this, but still need to be fixed - basically all of the unit tests where awaits were changed to voids and the .catchs were modified to fail faster - files including, but not limited to, apiCallable.ts and bundling.ts, locationService.ts, longrunning.ts, etc.
  • I've looked into alternatives, such as adopting nock, however those won't work without a large refactor as well (larger than this PR)

    • For the nock case, adopting it caused tests to fail because of the way we mock AbortController (a global, btw), and fixing that would be larger
  • I've landed on using GoogleAuth#fetch since that would things up in the last amount of work (still a lot) and would allow us to use better practices going forward

Understood, this makes sense. I think this is a reasonable alternative and a good choice given the circumstances. No issues with this choice.

  • These changes remove node-fetch usage, which we were mocking, thus the browser tests needed updating as well

To expedite this I would be happy to provide a walkthrough of these changes.

I appreciate the offer, but am happy to async review both PRs when this has been split up!

Thanks for clarifying - I’ll split out the async/void changes from this PR.

Just noting here, that if the other async/void PR isn’t merged, this library would remain in an unstable state.

done();
});
})
.catch(done);
Copy link
Contributor

Choose a reason for hiding this comment

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

If the assertion fails in 278, it's not caught by the .catch - the test instead fails because it times out after 2000ms. Was the intent of the new .catch to avoid that? If not, and it's fulfilling another purpose, I suspect that we had this problem before and I'll open an issue, but if so, it might need a small adjustment

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This catch is for the createStub call. We could further improve by fast-failing here - would you like me to add that?

Copy link
Contributor

Choose a reason for hiding this comment

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

given that we had this issue before, I will open up an issue to track and fast follow. The tests do fail, but we can make em "fail better". Opened a tracking issue https://github.com/googleapis/gax-nodejs/issues/1769

setMockFallbackResponse(
gaxGrpc,
new Response(JSON.stringify({}), {
status: 403,
Copy link
Contributor

Choose a reason for hiding this comment

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

why is the status 403 instead of OK like it was when we were attempting to proxyquire?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch - it didn't make a difference for the tested functionality, but I can make it match.

JSON.stringify(err.statusDetails),
JSON.stringify(expectedError.details),
);
done();
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure how quickly it was failing before, but right now even with the done in place, if the assertion error fails, it times out instead of failing fast

Copy link
Contributor

Choose a reason for hiding this comment

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

Comment on lines +569 to +574
it('should not send prettyPrint setting when json minification is not requested', done => {
const requestObject = {name: 'shelves/shelf-name'};
const responseObject = {
name: 'shelf-name',
theme: 'shelf-theme',
type: 100, // unknown enum value
Copy link
Contributor

Choose a reason for hiding this comment

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

what are these json minification tests? did they not exist before?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's strange - I merged and repaired from main and I fixed them here. Is this something you want removed or spun-off?

Copy link
Contributor

Choose a reason for hiding this comment

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

ugh hate when git syncs don't go as planned!
yeah if it doesn't have to do with this PR, let's spin it off into another in the name of small PRs please!

});
});

describe('should support json minification', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

added #1770 to track this quick re-add!

@leahecole leahecole self-assigned this Jun 6, 2025
@leahecole leahecole merged commit e7c686a into main Jun 6, 2025
28 checks passed
@leahecole leahecole deleted the fix-gax-tests branch June 6, 2025 19:06
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

size: xl Pull request size is extra large.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Some unit tests in grpc-fallback fail silently

3 participants