Skip to content

Commit 44d487f

Browse files
committed
fix: Add web component load error handling with a new onWebComponentLoadError prop to the DrivePicker component.
1 parent 535e7e8 commit 44d487f

File tree

4 files changed

+88
-2
lines changed

4 files changed

+88
-2
lines changed

packages/drive-picker-react/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ The available event handlers are:
5252
- `onPicked`
5353
- `onCanceled`
5454
- `onOauthError`
55+
- `onOauthError`
5556
- `onOauthResponse`
57+
- `onWebComponentLoadError`: Invoked if the underlying web component fails to load (e.g. network error).
5658

5759
The event argument is a `CustomEvent` where the `detail` property contains the payload from the Google Picker API.
5860

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { render, waitFor } from "@testing-library/react";
18+
import { describe, expect, it, vi } from "vitest";
19+
import { DrivePicker } from "./DrivePicker";
20+
import * as LoaderModule from "./loader";
21+
22+
describe("DrivePicker", () => {
23+
it("should call onWebComponentLoadError if import fails", async () => {
24+
const onWebComponentLoadError = vi.fn();
25+
const consoleErrorSpy = vi
26+
.spyOn(console, "error")
27+
.mockImplementation(() => {});
28+
29+
// Mock loader failure
30+
vi.spyOn(LoaderModule, "loadDrivePickerElement").mockRejectedValue(
31+
new Error("Import failed"),
32+
);
33+
34+
render(
35+
<DrivePicker
36+
client-id="test-client-id"
37+
app-id="test-app-id"
38+
onWebComponentLoadError={onWebComponentLoadError}
39+
/>,
40+
);
41+
42+
await waitFor(() => {
43+
expect(onWebComponentLoadError).toHaveBeenCalledWith(expect.any(Error));
44+
});
45+
46+
expect(onWebComponentLoadError).toHaveBeenCalledWith(
47+
expect.objectContaining({
48+
message: "Import failed",
49+
}),
50+
);
51+
52+
consoleErrorSpy.mockRestore();
53+
vi.restoreAllMocks();
54+
});
55+
});

packages/drive-picker-react/src/DrivePicker.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import type {
2323
import type React from "react";
2424
import { useEffect, useRef } from "react";
2525
import type { DrivePickerDocsViewProps } from "./DrivePickerDocsView";
26+
import { loadDrivePickerElement } from "./loader";
2627
import {
2728
type DrivePickerEventHandlers,
2829
useDrivePickerEvents,
@@ -50,6 +51,10 @@ export interface DrivePickerProps
5051
children?:
5152
| React.ReactElement<DrivePickerDocsViewProps>
5253
| React.ReactElement<DrivePickerDocsViewProps>[];
54+
/**
55+
* Callback invoked if the underlying web component fails to load.
56+
*/
57+
onWebComponentLoadError?: (error: Error) => void;
5358
}
5459

5560
/**
@@ -70,6 +75,7 @@ export const DrivePicker: React.FC<DrivePickerProps> = (props) => {
7075
onOauthError,
7176
onOauthResponse,
7277
children,
78+
onWebComponentLoadError,
7379
...rest
7480
} = props;
7581
const ref = useRef<DrivePickerElement>(null);
@@ -82,8 +88,13 @@ export const DrivePicker: React.FC<DrivePickerProps> = (props) => {
8288
});
8389

8490
useEffect(() => {
85-
import("@googleworkspace/drive-picker-element");
86-
}, []);
91+
loadDrivePickerElement().catch((e) => {
92+
console.error("Failed to load @googleworkspace/drive-picker-element", e);
93+
if (onWebComponentLoadError) {
94+
onWebComponentLoadError(e instanceof Error ? e : new Error(String(e)));
95+
}
96+
});
97+
}, [onWebComponentLoadError]);
8798

8899
return (
89100
<drive-picker ref={ref} {...rest}>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
export const loadDrivePickerElement = () =>
18+
import("@googleworkspace/drive-picker-element");

0 commit comments

Comments
 (0)