Add tests for Owner & move hooks to their own folder
Signed-off-by: Erik Engervall <erik.engervall@gmail.com>
This commit is contained in:
@@ -37,12 +37,16 @@ import { Info } from './cards/info/Info';
|
||||
import { InfoCardPlus } from './components/InfoCardPlus';
|
||||
import { isProjectValid } from './helpers/isProjectValid';
|
||||
import { Patch } from './cards/patchRc/Patch';
|
||||
import { ProjectContext, Project } from './contexts/ProjectContext';
|
||||
import {
|
||||
ProjectContext,
|
||||
Project,
|
||||
useProjectContext,
|
||||
} from './contexts/ProjectContext';
|
||||
import { PromoteRc } from './cards/promoteRc/PromoteRc';
|
||||
import { RefetchContext } from './contexts/RefetchContext';
|
||||
import { RepoDetailsForm } from './cards/projectForm/RepoDetailsForm';
|
||||
import { useVersioningStrategyMatchesRepoTags } from './helpers/useVersioningStrategyMatchesRepoTags';
|
||||
import { useQueryHandler } from './helpers/useQueryHandler';
|
||||
import { useVersioningStrategyMatchesRepoTags } from './hooks/useVersioningStrategyMatchesRepoTags';
|
||||
import { useQueryHandler } from './hooks/useQueryHandler';
|
||||
|
||||
interface GitHubReleaseManagerProps {
|
||||
components?: {
|
||||
@@ -92,32 +96,28 @@ export function GitHubReleaseManager({
|
||||
|
||||
return (
|
||||
<PluginApiClientContext.Provider value={pluginApiClient}>
|
||||
<div className={classes.root}>
|
||||
<ContentHeader title="GitHub Release Manager" />
|
||||
<ProjectContext.Provider value={project}>
|
||||
<div className={classes.root}>
|
||||
<ContentHeader title="GitHub Release Manager" />
|
||||
|
||||
<InfoCardPlus>
|
||||
<RepoDetailsForm
|
||||
username={usernameResponse.value.username}
|
||||
project={project}
|
||||
/>
|
||||
</InfoCardPlus>
|
||||
<InfoCardPlus>
|
||||
<RepoDetailsForm username={usernameResponse.value.username} />
|
||||
</InfoCardPlus>
|
||||
|
||||
{isProjectValid(project) && (
|
||||
<Cards components={components} project={project} />
|
||||
)}
|
||||
</div>
|
||||
{isProjectValid(project) && <Cards components={components} />}
|
||||
</div>
|
||||
</ProjectContext.Provider>
|
||||
</PluginApiClientContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
function Cards({
|
||||
components,
|
||||
project,
|
||||
}: {
|
||||
components: GitHubReleaseManagerProps['components'];
|
||||
project: Project;
|
||||
}) {
|
||||
const pluginApiClient = usePluginApiClientContext();
|
||||
const project = useProjectContext();
|
||||
const [refetchTrigger, setRefetchTrigger] = useState(0);
|
||||
const gitHubBatchInfo = useAsync(
|
||||
getGitHubBatchInfo({ project, pluginApiClient }),
|
||||
@@ -159,52 +159,50 @@ function Cards({
|
||||
}
|
||||
|
||||
return (
|
||||
<ProjectContext.Provider value={project}>
|
||||
<RefetchContext.Provider value={{ refetchTrigger, setRefetchTrigger }}>
|
||||
<ErrorBoundary>
|
||||
{gitHubBatchInfo.value.latestRelease && !versioningStrategyMatches && (
|
||||
<Alert severity="warning" style={{ marginBottom: 20 }}>
|
||||
Versioning mismatch, expected {project.versioningStrategy}{' '}
|
||||
version, got "{gitHubBatchInfo.value.latestRelease.tagName}"
|
||||
</Alert>
|
||||
)}
|
||||
<RefetchContext.Provider value={{ refetchTrigger, setRefetchTrigger }}>
|
||||
<ErrorBoundary>
|
||||
{gitHubBatchInfo.value.latestRelease && !versioningStrategyMatches && (
|
||||
<Alert severity="warning" style={{ marginBottom: 20 }}>
|
||||
Versioning mismatch, expected {project.versioningStrategy} version,
|
||||
got "{gitHubBatchInfo.value.latestRelease.tagName}"
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{!gitHubBatchInfo.value.latestRelease && (
|
||||
<Alert severity="info" style={{ marginBottom: 20 }}>
|
||||
This repository has not releases yet
|
||||
</Alert>
|
||||
)}
|
||||
{!gitHubBatchInfo.value.latestRelease && (
|
||||
<Alert severity="info" style={{ marginBottom: 20 }}>
|
||||
This repository has not releases yet
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Info
|
||||
<Info
|
||||
latestRelease={gitHubBatchInfo.value.latestRelease}
|
||||
releaseBranch={gitHubBatchInfo.value.releaseBranch}
|
||||
/>
|
||||
|
||||
{components?.default?.createRc?.omit !== true && (
|
||||
<CreateRc
|
||||
latestRelease={gitHubBatchInfo.value.latestRelease}
|
||||
releaseBranch={gitHubBatchInfo.value.releaseBranch}
|
||||
defaultBranch={gitHubBatchInfo.value.repository.defaultBranch}
|
||||
successCb={components?.default?.createRc?.successCb}
|
||||
/>
|
||||
)}
|
||||
|
||||
{components?.default?.createRc?.omit !== true && (
|
||||
<CreateRc
|
||||
latestRelease={gitHubBatchInfo.value.latestRelease}
|
||||
releaseBranch={gitHubBatchInfo.value.releaseBranch}
|
||||
defaultBranch={gitHubBatchInfo.value.repository.defaultBranch}
|
||||
successCb={components?.default?.createRc?.successCb}
|
||||
/>
|
||||
)}
|
||||
{components?.default?.promoteRc?.omit !== true && (
|
||||
<PromoteRc
|
||||
latestRelease={gitHubBatchInfo.value.latestRelease}
|
||||
successCb={components?.default?.promoteRc?.successCb}
|
||||
/>
|
||||
)}
|
||||
|
||||
{components?.default?.promoteRc?.omit !== true && (
|
||||
<PromoteRc
|
||||
latestRelease={gitHubBatchInfo.value.latestRelease}
|
||||
successCb={components?.default?.promoteRc?.successCb}
|
||||
/>
|
||||
)}
|
||||
|
||||
{components?.default?.patch?.omit !== true && (
|
||||
<Patch
|
||||
latestRelease={gitHubBatchInfo.value.latestRelease}
|
||||
releaseBranch={gitHubBatchInfo.value.releaseBranch}
|
||||
successCb={components?.default?.patch?.successCb}
|
||||
/>
|
||||
)}
|
||||
</ErrorBoundary>
|
||||
</RefetchContext.Provider>
|
||||
</ProjectContext.Provider>
|
||||
{components?.default?.patch?.omit !== true && (
|
||||
<Patch
|
||||
latestRelease={gitHubBatchInfo.value.latestRelease}
|
||||
releaseBranch={gitHubBatchInfo.value.releaseBranch}
|
||||
successCb={components?.default?.patch?.successCb}
|
||||
/>
|
||||
)}
|
||||
</ErrorBoundary>
|
||||
</RefetchContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* 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 React from 'react';
|
||||
import { render, waitFor, screen } from '@testing-library/react';
|
||||
|
||||
import {
|
||||
mockApiClient,
|
||||
mockCalverProject,
|
||||
} from '../../test-helpers/test-helpers';
|
||||
import { TEST_IDS } from '../../test-helpers/test-ids';
|
||||
|
||||
jest.mock('react-router', () => ({
|
||||
useNavigate: jest.fn(),
|
||||
useLocation: jest.fn(() => ({
|
||||
search: `?versioningStrategy=${mockCalverProject.versioningStrategy}&owner=${mockCalverProject.owner}&repo=${mockCalverProject.repo}`,
|
||||
})),
|
||||
}));
|
||||
jest.mock('../../contexts/PluginApiClientContext', () => ({
|
||||
usePluginApiClientContext: jest.fn(() => mockApiClient),
|
||||
}));
|
||||
jest.mock('../../contexts/ProjectContext', () => ({
|
||||
useProjectContext: jest.fn(() => mockCalverProject),
|
||||
}));
|
||||
|
||||
import { useProjectContext } from '../../contexts/ProjectContext';
|
||||
import { Owner } from './Owner';
|
||||
|
||||
describe('Owner', () => {
|
||||
beforeEach(jest.clearAllMocks);
|
||||
|
||||
it('should render select', async () => {
|
||||
const { getByTestId } = render(
|
||||
<Owner username={mockCalverProject.owner} />,
|
||||
);
|
||||
|
||||
expect(getByTestId(TEST_IDS.form.owner.loading)).toBeInTheDocument();
|
||||
|
||||
await waitFor(() => screen.getByTestId(TEST_IDS.form.owner.select));
|
||||
expect(getByTestId(TEST_IDS.form.owner.select)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render select for empty owners', async () => {
|
||||
(useProjectContext as jest.Mock).mockImplementation(() => ({
|
||||
...mockCalverProject,
|
||||
owner: '',
|
||||
}));
|
||||
|
||||
const { getAllByTestId, getByTestId } = render(
|
||||
<Owner username={mockCalverProject.owner} />,
|
||||
);
|
||||
|
||||
expect(getByTestId(TEST_IDS.form.owner.loading)).toBeInTheDocument();
|
||||
|
||||
await waitFor(() => screen.getAllByTestId(TEST_IDS.form.owner.empty));
|
||||
expect(getAllByTestId(TEST_IDS.form.owner.empty)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
<p
|
||||
class="MuiFormHelperText-root Mui-required"
|
||||
data-testid="grm--form--owner--empty"
|
||||
>
|
||||
Select an owner (org or user)
|
||||
</p>,
|
||||
<p
|
||||
class="MuiFormHelperText-root Mui-required"
|
||||
data-testid="grm--form--owner--empty"
|
||||
>
|
||||
Custom queries can be made via the query param
|
||||
|
||||
<strong>
|
||||
owner
|
||||
</strong>
|
||||
</p>,
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('should handle errors', async () => {
|
||||
(mockApiClient.getOwners as jest.Mock).mockImplementationOnce(async () => {
|
||||
throw new Error('Kaboom');
|
||||
});
|
||||
|
||||
const { getByTestId } = render(
|
||||
<Owner username={mockCalverProject.owner} />,
|
||||
);
|
||||
|
||||
expect(getByTestId(TEST_IDS.form.owner.loading)).toBeInTheDocument();
|
||||
await waitFor(() => screen.getByTestId(TEST_IDS.form.owner.error));
|
||||
expect(getByTestId(TEST_IDS.form.owner.error)).toMatchInlineSnapshot(`
|
||||
<p
|
||||
class="MuiFormHelperText-root Mui-error Mui-required"
|
||||
data-testid="grm--form--owner--error"
|
||||
>
|
||||
Encountered an error (
|
||||
Kaboom
|
||||
)
|
||||
</p>
|
||||
`);
|
||||
});
|
||||
});
|
||||
@@ -26,18 +26,14 @@ import {
|
||||
} from '@material-ui/core';
|
||||
|
||||
import { CenteredCircularProgress } from '../../components/CenteredCircularProgress';
|
||||
import { Project } from '../../contexts/ProjectContext';
|
||||
import { useFormClasses } from './styles';
|
||||
import { usePluginApiClientContext } from '../../contexts/PluginApiClientContext';
|
||||
import { useQueryHandler } from '../../helpers/useQueryHandler';
|
||||
import { useProjectContext } from '../../contexts/ProjectContext';
|
||||
import { useQueryHandler } from '../../hooks/useQueryHandler';
|
||||
import { TEST_IDS } from '../../test-helpers/test-ids';
|
||||
|
||||
export function Owner({
|
||||
username,
|
||||
project,
|
||||
}: {
|
||||
username: string;
|
||||
project: Project;
|
||||
}) {
|
||||
export function Owner({ username }: { username: string }) {
|
||||
const project = useProjectContext();
|
||||
const formClasses = useFormClasses();
|
||||
const navigate = useNavigate();
|
||||
const pluginApiClient = usePluginApiClientContext();
|
||||
@@ -52,11 +48,12 @@ export function Owner({
|
||||
return (
|
||||
<FormControl className={formClasses.formControl} required error={!!error}>
|
||||
{loading ? (
|
||||
<CenteredCircularProgress />
|
||||
<CenteredCircularProgress data-testid={TEST_IDS.form.owner.loading} />
|
||||
) : (
|
||||
<>
|
||||
<InputLabel id="owner-select-label">Owners</InputLabel>
|
||||
<Select
|
||||
data-testid={TEST_IDS.form.owner.select}
|
||||
labelId="owner-select-label"
|
||||
id="owner-select"
|
||||
value={project.owner}
|
||||
@@ -95,15 +92,17 @@ export function Owner({
|
||||
</Select>
|
||||
|
||||
{error && (
|
||||
<FormHelperText>
|
||||
<FormHelperText data-testid={TEST_IDS.form.owner.error}>
|
||||
Encountered an error ({error.message})
|
||||
</FormHelperText>
|
||||
)}
|
||||
|
||||
{!error && project.owner.length === 0 && (
|
||||
<>
|
||||
<FormHelperText>Select an owner (org or user)</FormHelperText>
|
||||
<FormHelperText>
|
||||
<FormHelperText data-testid={TEST_IDS.form.owner.empty}>
|
||||
Select an owner (org or user)
|
||||
</FormHelperText>
|
||||
<FormHelperText data-testid={TEST_IDS.form.owner.empty}>
|
||||
Custom queries can be made via the query param{' '}
|
||||
<strong>owner</strong>
|
||||
</FormHelperText>
|
||||
|
||||
@@ -28,11 +28,12 @@ import {
|
||||
import { usePluginApiClientContext } from '../../contexts/PluginApiClientContext';
|
||||
import { useFormClasses } from './styles';
|
||||
import { CenteredCircularProgress } from '../../components/CenteredCircularProgress';
|
||||
import { Project } from '../../contexts/ProjectContext';
|
||||
import { useQueryHandler } from '../../helpers/useQueryHandler';
|
||||
import { useProjectContext } from '../../contexts/ProjectContext';
|
||||
import { useQueryHandler } from '../../hooks/useQueryHandler';
|
||||
|
||||
export function Repo({ project }: { project: Project }) {
|
||||
export function Repo() {
|
||||
const pluginApiClient = usePluginApiClientContext();
|
||||
const project = useProjectContext();
|
||||
const navigate = useNavigate();
|
||||
const formClasses = useFormClasses();
|
||||
const { getQueryParamsWithUpdates } = useQueryHandler();
|
||||
@@ -42,6 +43,10 @@ export function Repo({ project }: { project: Project }) {
|
||||
[project.owner],
|
||||
);
|
||||
|
||||
if (project.owner.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const repositories = value?.repositories ?? [];
|
||||
const customRepoFromUrl = !repositories.concat(['']).includes(project.repo);
|
||||
|
||||
|
||||
@@ -17,24 +17,17 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Owner } from './Owner';
|
||||
import { Project } from '../../contexts/ProjectContext';
|
||||
import { Repo } from './Repo';
|
||||
import { VersioningStrategy } from './VersioningStrategy';
|
||||
|
||||
export function RepoDetailsForm({
|
||||
username,
|
||||
project,
|
||||
}: {
|
||||
username: string;
|
||||
project: Project;
|
||||
}) {
|
||||
export function RepoDetailsForm({ username }: { username: string }) {
|
||||
return (
|
||||
<>
|
||||
<VersioningStrategy project={project} />
|
||||
<VersioningStrategy />
|
||||
|
||||
<Owner project={project} username={username} />
|
||||
<Owner username={username} />
|
||||
|
||||
{project.owner.length > 0 && <Repo project={project} />}
|
||||
<Repo />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -24,11 +24,12 @@ import {
|
||||
RadioGroup,
|
||||
} from '@material-ui/core';
|
||||
|
||||
import { Project } from '../../contexts/ProjectContext';
|
||||
import { useQueryHandler } from '../../helpers/useQueryHandler';
|
||||
import { Project, useProjectContext } from '../../contexts/ProjectContext';
|
||||
import { useQueryHandler } from '../../hooks/useQueryHandler';
|
||||
|
||||
export function VersioningStrategy({ project }: { project: Project }) {
|
||||
export function VersioningStrategy() {
|
||||
const navigate = useNavigate();
|
||||
const project = useProjectContext();
|
||||
const { getParsedQuery, getQueryParamsWithUpdates } = useQueryHandler();
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { Project } from '../contexts/ProjectContext';
|
||||
import { getTagParts } from './tagParts/getTagParts';
|
||||
import { getTagParts } from '../helpers/tagParts/getTagParts';
|
||||
|
||||
export const useVersioningStrategyMatchesRepoTags = ({
|
||||
project,
|
||||
@@ -35,6 +35,14 @@ export const TEST_IDS = {
|
||||
notPrerelease: 'grm--patch-body--not-prerelease--info',
|
||||
body: 'grm--patch-body',
|
||||
},
|
||||
form: {
|
||||
owner: {
|
||||
loading: 'grm--form--owner--loading',
|
||||
select: 'grm--form--owner--select',
|
||||
error: 'grm--form--owner--error',
|
||||
empty: 'grm--form--owner--empty',
|
||||
},
|
||||
},
|
||||
components: {
|
||||
divider: 'grm--divider',
|
||||
reloadButton: 'grm--reload-button',
|
||||
|
||||
Reference in New Issue
Block a user