test(scaffolder): editor toolbar templates menu
Signed-off-by: Camila Belo <camilaibs@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Add tests for the `useTemplateDirectory` hook.
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
} from '../../../routes';
|
||||
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
|
||||
import { scaffolderTranslationRef } from '../../../translation';
|
||||
import { WebFileSystemStore } from '../../../lib/filesystem/WebFileSystemAccess';
|
||||
import { WebFileSystemStore } from '../../../lib/filesystem/WebFileSystemStore';
|
||||
import { createExampleTemplate } from '../../../lib/filesystem/createExampleTemplate';
|
||||
|
||||
export function TemplateIntroPage() {
|
||||
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { act, renderHook, waitFor } from '@testing-library/react';
|
||||
import { useTemplateDirectory } from './useTemplateDirectory';
|
||||
import {
|
||||
createExampleTemplate,
|
||||
TemplateDirectoryAccess,
|
||||
WebFileSystemStore,
|
||||
} from '../../../lib/filesystem';
|
||||
import {
|
||||
IterableDirectoryHandle,
|
||||
WebFileSystemAccess,
|
||||
} from '../../../lib/filesystem/WebFileSystemAccess';
|
||||
|
||||
jest.mock('../../../lib/filesystem/createExampleTemplate');
|
||||
|
||||
describe('useTemplateDirectory', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should return undefined when there is no existing directory in the file system store', async () => {
|
||||
jest.spyOn(WebFileSystemStore, 'getDirectory').mockResolvedValue(undefined);
|
||||
|
||||
const { result } = renderHook(() => useTemplateDirectory());
|
||||
|
||||
expect(result.current.directory).toBeUndefined();
|
||||
expect(result.current.loading).toBeTruthy();
|
||||
expect(result.current.error).toBeUndefined();
|
||||
|
||||
await waitFor(() => expect(result.current.loading).toBeFalsy());
|
||||
|
||||
expect(result.current.directory).toBeUndefined();
|
||||
expect(result.current.error).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return an access when there is existing directory in the file system store', async () => {
|
||||
const handle = {} as IterableDirectoryHandle;
|
||||
|
||||
jest.spyOn(WebFileSystemStore, 'getDirectory').mockResolvedValue(handle);
|
||||
|
||||
const { result } = renderHook(() => useTemplateDirectory());
|
||||
|
||||
await waitFor(() => expect(result.current.loading).toBeFalsy());
|
||||
|
||||
expect(result.current.directory).toMatchObject({ handle });
|
||||
expect(result.current.error).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle opening a directory', async () => {
|
||||
const handle = {};
|
||||
jest
|
||||
.spyOn(WebFileSystemStore, 'getDirectory')
|
||||
.mockResolvedValue(handle as IterableDirectoryHandle);
|
||||
const setDirectory = jest
|
||||
.spyOn(WebFileSystemStore, 'setDirectory')
|
||||
.mockResolvedValue(undefined);
|
||||
const requestDirectoryAccess = jest
|
||||
.spyOn(WebFileSystemAccess, 'requestDirectoryAccess')
|
||||
.mockResolvedValue(handle as TemplateDirectoryAccess);
|
||||
|
||||
const { result } = renderHook(() => useTemplateDirectory());
|
||||
|
||||
expect(result.current.directory).toBeUndefined();
|
||||
|
||||
await act(async () => {
|
||||
result.current.handleOpenDirectory();
|
||||
});
|
||||
|
||||
expect(requestDirectoryAccess).toHaveBeenCalled();
|
||||
expect(setDirectory).toHaveBeenCalledWith(handle);
|
||||
|
||||
await waitFor(() => expect(result.current.directory).toBeDefined());
|
||||
});
|
||||
|
||||
it('should handle creating a directory', async () => {
|
||||
const handle = {};
|
||||
(createExampleTemplate as jest.Mock).mockResolvedValue(handle);
|
||||
jest
|
||||
.spyOn(WebFileSystemStore, 'getDirectory')
|
||||
.mockResolvedValue(handle as IterableDirectoryHandle);
|
||||
const setDirectory = jest
|
||||
.spyOn(WebFileSystemStore, 'setDirectory')
|
||||
.mockResolvedValue(undefined);
|
||||
const requestDirectoryAccess = jest
|
||||
.spyOn(WebFileSystemAccess, 'requestDirectoryAccess')
|
||||
.mockResolvedValue(handle as TemplateDirectoryAccess);
|
||||
|
||||
const { result } = renderHook(() => useTemplateDirectory());
|
||||
|
||||
await act(async () => {
|
||||
result.current.handleCreateDirectory();
|
||||
});
|
||||
|
||||
expect(requestDirectoryAccess).toHaveBeenCalled();
|
||||
expect(setDirectory).toHaveBeenCalledWith(handle);
|
||||
expect(createExampleTemplate).toHaveBeenCalledWith(handle);
|
||||
});
|
||||
|
||||
it('should handle closing a directory', async () => {
|
||||
jest.spyOn(WebFileSystemStore, 'getDirectory').mockResolvedValue(undefined);
|
||||
|
||||
const setDirectory = jest
|
||||
.spyOn(WebFileSystemStore, 'setDirectory')
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
const { result } = renderHook(() => useTemplateDirectory());
|
||||
|
||||
expect(setDirectory).not.toHaveBeenCalled();
|
||||
expect(result.current.directory).toBeUndefined();
|
||||
|
||||
await act(async () => {
|
||||
result.current.handleCloseDirectory();
|
||||
});
|
||||
|
||||
expect(setDirectory).toHaveBeenCalledWith(undefined);
|
||||
await waitFor(() => expect(result.current.directory).toBeUndefined());
|
||||
});
|
||||
});
|
||||
@@ -18,11 +18,11 @@ import { useCallback } from 'react';
|
||||
import useAsyncRetry from 'react-use/esm/useAsyncRetry';
|
||||
|
||||
import {
|
||||
WebFileSystemAccess,
|
||||
WebFileSystemStore,
|
||||
WebFileSystemAccess,
|
||||
WebDirectoryAccess,
|
||||
createExampleTemplate,
|
||||
} from '../../../lib/filesystem';
|
||||
import { createExampleTemplate } from '../../../lib/filesystem/createExampleTemplate';
|
||||
|
||||
export function useTemplateDirectory(): {
|
||||
directory?: WebDirectoryAccess;
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { get, set } from 'idb-keyval';
|
||||
import { TemplateDirectoryAccess, TemplateFileAccess } from './types';
|
||||
|
||||
type WritableFileHandle = FileSystemFileHandle & {
|
||||
@@ -25,7 +24,7 @@ type WritableFileHandle = FileSystemFileHandle & {
|
||||
};
|
||||
|
||||
// A nicer type than the one from the TS lib
|
||||
interface IterableDirectoryHandle extends FileSystemDirectoryHandle {
|
||||
export interface IterableDirectoryHandle extends FileSystemDirectoryHandle {
|
||||
values(): AsyncIterable<
|
||||
| ({ kind: 'file' } & WritableFileHandle)
|
||||
| ({ kind: 'directory' } & IterableDirectoryHandle)
|
||||
@@ -124,16 +123,3 @@ export class WebFileSystemAccess {
|
||||
|
||||
private constructor() {}
|
||||
}
|
||||
|
||||
export class WebFileSystemStore {
|
||||
private static readonly key = 'scalfolder-template-editor-directory';
|
||||
|
||||
static async getDirectory(): Promise<IterableDirectoryHandle | undefined> {
|
||||
const directory = await get(WebFileSystemStore.key);
|
||||
return directory.handle;
|
||||
}
|
||||
|
||||
static async setDirectory(directory: TemplateDirectoryAccess | undefined) {
|
||||
return set(WebFileSystemStore.key, directory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { get, set } from 'idb-keyval';
|
||||
import { TemplateDirectoryAccess } from './types';
|
||||
import { IterableDirectoryHandle } from './WebFileSystemAccess';
|
||||
|
||||
export class WebFileSystemStore {
|
||||
private static readonly key = 'scalfolder-template-editor-directory';
|
||||
|
||||
static async getDirectory(): Promise<IterableDirectoryHandle | undefined> {
|
||||
const directory = await get(WebFileSystemStore.key);
|
||||
return directory.handle;
|
||||
}
|
||||
|
||||
static async setDirectory(directory: TemplateDirectoryAccess | undefined) {
|
||||
return set(WebFileSystemStore.key, directory);
|
||||
}
|
||||
}
|
||||
@@ -14,10 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export type { TemplateFileAccess, TemplateDirectoryAccess } from './types';
|
||||
export { blobToBase64 } from './helpers';
|
||||
export {
|
||||
WebDirectoryAccess,
|
||||
WebFileSystemAccess,
|
||||
WebFileSystemStore,
|
||||
} from './WebFileSystemAccess';
|
||||
export { createExampleTemplate } from './createExampleTemplate';
|
||||
export type { TemplateFileAccess, TemplateDirectoryAccess } from './types';
|
||||
export { WebFileSystemStore } from './WebFileSystemStore';
|
||||
export { WebDirectoryAccess, WebFileSystemAccess } from './WebFileSystemAccess';
|
||||
|
||||
Reference in New Issue
Block a user