Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('ParamList', () => {
const PARAM = 'pirojok-the-param';
const LABEL = 'pirojok-the-label';
const VALUE = 'pirojok-the-value';
const extension: Extension = {
const staticExtension: Extension = {
id,
params: [
{
Expand All @@ -39,6 +39,28 @@ describe('ParamList', () => {
],
} as Extension;

const dynId = 'dyn-pirojok';
const DYN_DESCRIPTION = 'dyn-pirojok-the-description';
const DYN_PARAM = 'dyn-pirojok-the-param';
const DYN_LABEL = 'dyn-pirojok-the-label';
const DYN_VALUE = 'dyn-pirojok-the-value';
const LABELS: Record<string, string> = {
createdBy: 'SDK',
codebase: 'default',
};
const dynamicExtension: Extension = {
id: dynId,
params: [
{
param: DYN_PARAM,
label: DYN_LABEL,
value: DYN_VALUE,
description: DYN_DESCRIPTION,
},
],
labels: LABELS,
} as Extension;

function setup(extension: Extension, id: string) {
return render(
<TestExtensionsProvider extensions={[extension]} instanceId={id}>
Expand All @@ -47,20 +69,36 @@ describe('ParamList', () => {
);
}

it('renders list of parameters', () => {
const { getByText } = setup(extension, id);
it('renders list of parameters for static extensions', () => {
const { getByText } = setup(staticExtension, id);

expect(getByText(new RegExp(LABEL))).not.toBeNull();
expect(getByText(new RegExp(VALUE))).not.toBeNull();
});

it('displays param description on expansion in markdown', () => {
const { getByText } = setup(extension, id);
it('renders list of parameters for dynamic extensions', () => {
const { getByText } = setup(dynamicExtension, dynId);

expect(getByText(new RegExp(DYN_LABEL))).not.toBeNull();
expect(getByText(new RegExp(DYN_VALUE))).not.toBeNull();
});

it('displays param description on expansion in markdown for static', () => {
const { getByText } = setup(staticExtension, id);

act(() => {
getByText(new RegExp(LABEL)).click();
});
expect(getByText(new RegExp(DESCRIPTION))).not.toBeNull();
expect(getByText(new RegExp(DESCRIPTION))).not.toBeNull();
});

it('displays param description on expansion in markdown for dynamic', () => {
const { getByText } = setup(dynamicExtension, dynId);

act(() => {
getByText(new RegExp(DYN_LABEL)).click();
});
expect(getByText(new RegExp(DYN_DESCRIPTION))).not.toBeNull();
});
});
55 changes: 35 additions & 20 deletions src/components/Extensions/Details/DetailCard/Tabs/ParamList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,51 @@ import { Callout } from '../../../../common/Callout';
import { DOCS_BASE } from '../../../../common/links/DocsLink';
import { Markdown } from '../../../../common/Markdown';
import { useExtension } from '../../../api/useExtension';
import { isDynamicExtension } from '../../../api/useExtensions';
import { EventsConfig } from './EventsConfig';
import styles from './ParamList.module.scss';
import { ParamValue } from './ParamValue';

function ParamList() {
const extension = useExtension()!;
const isDynamic = isDynamicExtension(extension);
const docSuffix = isDynamic
? 'extensions/manage-installed-extensions?interface=sdk#reconfigure'
: 'extensions/manifest';

const dynamicFragment = (
<Typography use="body2">
Reconfigure is not available in the emulator. You can reconfigure
parameters by updating them in the code.
</Typography>
);

const staticFragment = (
<>
<Typography use="body2">
Reconfigure is not available in the emulator. You can reconfigure
parameters by updating your .env files with:
</Typography>
<br />
<code>firebase ext:configure {extension.id} --local</code>)
</>
);

return (
<div>
<div className={styles.paramHeader}>
<Callout aside type="note">
<Accordion
title={
<Typography use="body2">
Reconfigure is not available in the emulator. You can
reconfigure parameters by <b>updating your .env files</b> with:
</Typography>
}
>
<code>firebase ext:configure {extension.id} --local</code>
<div className={styles.learnButton}>
<a
href={DOCS_BASE + 'extensions/manifest'}
target="_blank"
rel="noopener noreferrer"
tabIndex={-1}
>
<Button>Learn more</Button>
</a>
</div>
</Accordion>
{isDynamic ? dynamicFragment : staticFragment}
<div className={styles.learnButton}>
<a
href={DOCS_BASE + docSuffix}
target="_blank"
Copy link
Contributor

Choose a reason for hiding this comment

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

You can use the ExternalLink component here, also why a tab-index of -1?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

discussed offline. This is ok.

rel="noopener noreferrer"
tabIndex={-1}
>
<Button>Learn more</Button>
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm I don't think we should have buttons inside of anchors... that's not valid HTML

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discussed offline. This is ok.

</a>
</div>
</Callout>
</div>
{(extension.params || []).map((param) => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/Extensions/List/ExtensionsCallout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ export const ExtensionCallout: React.FC<
actions={
<div className={styles.link}>
<DocsLink
href="extensions/manifest"
href="extensions/manage-installed-extensions"
target="_blank"
rel="noopener noreferrer"
>
<Typography theme="primary" use="body2" className={styles.link}>
Learn how to manage your extensions manifest
Learn how to manage your extensions
</Typography>
</DocsLink>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ export const ExtensionsTableRow: React.FC<
{extension.ref}
</Typography>
</div>
<div>
<Typography use="body2" theme="textSecondaryOnBackground">
{extension.id}
</Typography>
</div>
</DataTableCell>
<DataTableCell className={`${styles.actionCell} actionCell`}>
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ describe('useExtensionBackends', () => {
await waitFor(() => result.current !== null);
await waitFor(() => delay(100));

expect(result.current).toEqual([BACKEND_LIST[0], BACKEND_LIST[1]]);
expect(result.current).toEqual([
BACKEND_LIST[0],
BACKEND_LIST[1],
BACKEND_LIST[2],
]);
});
});
64 changes: 62 additions & 2 deletions src/components/Extensions/api/internal/useExtensionsData.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ describe('useExtensionsData', () => {

expect(result.current).toEqual([
{
id: 'pirojok-the-published-extension',
authorName: 'Awesome Inc',
authorUrl: 'https://google.com/awesome',
params: [],
Expand Down Expand Up @@ -93,14 +94,15 @@ describe('useExtensionsData', () => {
sourceUrl: '',
extensionDetailsUrl:
'https://firebase.google.com/products/extensions/good-tool',
id: 'pirojok-the-published-extension',

ref: 'awesome-inc/[email protected]',
iconUri:
'https://www.gstatic.com/mobilesdk/211001_mobilesdk/google-pay-logo.svg',
publisherIconUri:
'https://www.gstatic.com/mobilesdk/160503_mobilesdk/logo/2x/firebase_128dp.png',
},
{
id: 'pirojok-the-local-extension',
authorName: 'Awesome Inc',
authorUrl: 'https://google.com/awesome',
params: [],
Expand Down Expand Up @@ -150,7 +152,65 @@ describe('useExtensionsData', () => {
sourceUrl: '',
extensionDetailsUrl:
'https://firebase.google.com/products/extensions/good-tool',
id: 'pirojok-the-local-extension',
},
{
id: 'pirojok-the-dynamic-extension',
authorName: 'Awesome Inc',
authorUrl: 'https://google.com/awesome',
params: [],
name: 'good-tool',
displayName: 'Pirojok-the-tool',
specVersion: 'v1beta',
env: {
ALLOWED_EVENT_TYPES: 'google.firebase.v1.custom-event-occurred',
EVENTARC_CHANNEL:
'projects/test-project/locations/us-west1/channels/firebase',
},
allowedEventTypes: ['google.firebase.v1.custom-event-occurred'],
eventarcChannel:
'projects/test-project/locations/us-west1/channels/firebase',
events: [
{
type: 'google.firebase.v1.custom-event-occurred',
description: 'A custom event occurred',
},
],
apis: [
{
apiName: 'storage-component.googleapis.com',
reason: 'Needed to use Cloud Storage',
},
],
resources: [
{
type: 'firebaseextensions.v1beta.function',
description:
'Listens for new images uploaded to your specified Cloud Storage bucket, resizes the images, then stores the resized images in the same bucket. Optionally keeps or deletes the original images.',
name: 'generateResizedImage',
propertiesYaml:
// eslint-disable-next-line no-template-curly-in-string
'availableMemoryMb: 1024\neventTrigger:\n eventType: google.storage.object.finalize\n resource: projects/_/buckets/${param:IMG_BUCKET}\nlocation: ${param:LOCATION}\nruntime: nodejs14\n',
},
],
roles: [
{
role: 'storage.admin',
reason:
'Allows the extension to store resized images in Cloud Storage',
},
],
readmeContent: '',
postinstallContent: '### See it in action',
sourceUrl: '',
extensionDetailsUrl:
'https://firebase.google.com/products/extensions/good-tool',

ref: 'awesome-inc/[email protected]',
iconUri:
'https://www.gstatic.com/mobilesdk/211001_mobilesdk/google-pay-logo.svg',
publisherIconUri:
'https://www.gstatic.com/mobilesdk/160503_mobilesdk/logo/2x/firebase_128dp.png',
labels: { createdBy: 'SDK', codebase: 'default' },
},
]);
});
Expand Down
15 changes: 11 additions & 4 deletions src/components/Extensions/api/internal/useExtensionsData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
* limitations under the License.
*/
import { Extension, ExtensionResource, Resource } from '../../models';
import { ExtensionBackend, isLocalExtension } from '../useExtensions';
import {
ExtensionBackend,
isDynamicExtension,
isLocalExtension,
} from '../useExtensions';
import { useExtensionBackends } from './useExtensionBackends';

const EXTENSION_DETAILS_URL_BASE =
Expand Down Expand Up @@ -46,7 +50,8 @@ export function convertBackendToExtension(
: r;
};

const shared = {
const shared: Omit<Extension, 'authorName'> = {
id: backend.extensionInstanceId,
authorUrl: spec.author?.url ?? '',
params: spec.params.map((p) => {
return {
Expand All @@ -70,17 +75,19 @@ export function convertBackendToExtension(
extensionDetailsUrl: EXTENSION_DETAILS_URL_BASE + spec.name,
};

if (isDynamicExtension(backend)) {
shared.labels = backend.labels;
}

if (isLocalExtension(backend)) {
return {
...shared,
authorName: spec.author?.authorName ?? '',
id: backend.extensionInstanceId,
};
}

return {
...shared,
id: backend.extensionInstanceId,
ref: backend.extensionVersion.ref,
authorName:
spec.author?.authorName ??
Expand Down
18 changes: 16 additions & 2 deletions src/components/Extensions/api/useExtensions.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

import { renderHook } from '@testing-library/react';

import { EXTENSION } from '../testing/utils';
import { DYNAMIC_EXTENSION, EXTENSION } from '../testing/utils';
import { ExtensionsProvider, useExtensions } from './useExtensions';

describe('useExtensions', () => {
it('returns the list of extension backends', () => {
it('returns the list of static extension backends', () => {
const wrapper: React.FC<React.PropsWithChildren<unknown>> = ({
children,
}) => (
Expand All @@ -33,4 +33,18 @@ describe('useExtensions', () => {

expect(result.current).toEqual([EXTENSION]);
});

it('returns the list of dynamic extension backends', () => {
const wrapper: React.FC<React.PropsWithChildren<unknown>> = ({
children,
}) => (
<ExtensionsProvider extensions={[DYNAMIC_EXTENSION]}>
{children}
</ExtensionsProvider>
);

const { result } = renderHook(() => useExtensions(), { wrapper });

expect(result.current).toEqual([DYNAMIC_EXTENSION]);
});
});
7 changes: 7 additions & 0 deletions src/components/Extensions/api/useExtensions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface CommonExtensionBackend {
env: Record<string, string>;
extensionInstanceId: string;
functionTriggers: FunctionTrigger[];
labels?: Record<string, string>;
}

interface PublishedExtensionBackend extends CommonExtensionBackend {
Expand Down Expand Up @@ -72,3 +73,9 @@ export function isLocalExtension(
): backend is LocalExtensionBackend {
return backend.hasOwnProperty('extensionSpec');
}

export function isDynamicExtension(
extension: Extension | ExtensionBackend
): boolean {
return extension.labels?.createdBy === 'SDK';
}
3 changes: 3 additions & 0 deletions src/components/Extensions/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ export interface Extension {
sourceUrl: string;
postinstallContent: string;
extensionDetailsUrl: string;
name?: string;
env?: Record<string, string>;
labels?: Record<string, string>;
}

export interface ExternalService {
Expand Down
Loading
Loading