Improve a11y (#1841)

Improve accessibility by removing unnecessary tags without hrefs. Also remove many eslint errors and warnings.
This commit is contained in:
Eduard Heimbuch
2021-11-04 09:16:08 +01:00
committed by GitHub
parent 0efdd2a483
commit 6f61fefec5
213 changed files with 1924 additions and 2068 deletions

View File

@@ -0,0 +1,4 @@
- type: fixed
description: Fix <a> tags without hrefs ([#1841](https://github.com/scm-manager/scm-manager/pull/1841))
- type: fixed
description: Fix eslint errors and warnings ([#1841](https://github.com/scm-manager/scm-manager/pull/1841))

View File

@@ -32,7 +32,7 @@ import {
Loading, Loading,
Subtitle, Subtitle,
Level, Level,
SubmitButton SubmitButton,
} from "@scm-manager/ui-components"; } from "@scm-manager/ui-components";
type Props = WithTranslation & { type Props = WithTranslation & {
@@ -67,40 +67,40 @@ class RepositoryConfig extends React.Component<Props, State> {
nonFastForwardDisallowed: false, nonFastForwardDisallowed: false,
changesSubmitted: false, changesSubmitted: false,
disabled: true, disabled: true,
changed: false changed: false,
}; };
} }
componentDidMount() { componentDidMount() {
const { repository } = this.props; const { repository } = this.props;
this.setState({ this.setState({
loadingBranches: true loadingBranches: true,
}); });
const branchesLink = repository._links.branches as Link; const branchesLink = repository._links.branches as Link;
apiClient apiClient
.get(branchesLink.href) .get(branchesLink.href)
.then(response => response.json()) .then((response) => response.json())
.then(payload => payload._embedded.branches) .then((payload) => payload._embedded.branches)
.then(branches => .then((branches) =>
this.setState({ this.setState({
branches, branches,
loadingBranches: false loadingBranches: false,
}) })
) )
.catch(error => .catch((error) =>
this.setState({ this.setState({
error error,
}) })
); );
const configurationLink = repository._links.configuration as Link; const configurationLink = repository._links.configuration as Link;
this.setState({ this.setState({
loadingDefaultBranch: true loadingDefaultBranch: true,
}); });
apiClient apiClient
.get(configurationLink.href) .get(configurationLink.href)
.then(response => response.json()) .then((response) => response.json())
.then(payload => { .then((payload) => {
const defaultBranch = const defaultBranch =
payload.defaultBranch || this.state.branches?.filter((b: Branch) => b.defaultBranch)[0]?.name; payload.defaultBranch || this.state.branches?.filter((b: Branch) => b.defaultBranch)[0]?.name;
this.setState({ this.setState({
@@ -108,12 +108,12 @@ class RepositoryConfig extends React.Component<Props, State> {
nonFastForwardDisallowed: payload.nonFastForwardDisallowed, nonFastForwardDisallowed: payload.nonFastForwardDisallowed,
disabled: !payload._links.update, disabled: !payload._links.update,
loadingDefaultBranch: false, loadingDefaultBranch: false,
changed: false changed: false,
}); });
}) })
.catch(error => .catch((error) =>
this.setState({ this.setState({
error error,
}) })
); );
} }
@@ -123,13 +123,13 @@ class RepositoryConfig extends React.Component<Props, State> {
this.setState({ this.setState({
selectedBranchName: "", selectedBranchName: "",
changesSubmitted: false, changesSubmitted: false,
changed: true changed: true,
}); });
} else { } else {
this.setState({ this.setState({
selectedBranchName: branch.name, selectedBranchName: branch.name,
changesSubmitted: false, changesSubmitted: false,
changed: true changed: true,
}); });
} }
}; };
@@ -137,7 +137,7 @@ class RepositoryConfig extends React.Component<Props, State> {
onNonFastForwardDisallowed = (value: boolean) => { onNonFastForwardDisallowed = (value: boolean) => {
this.setState({ this.setState({
nonFastForwardDisallowed: value, nonFastForwardDisallowed: value,
changed: true changed: true,
}); });
}; };
@@ -148,10 +148,10 @@ class RepositoryConfig extends React.Component<Props, State> {
const { selectedBranchName, nonFastForwardDisallowed } = this.state; const { selectedBranchName, nonFastForwardDisallowed } = this.state;
const newConfig = { const newConfig = {
defaultBranch: selectedBranchName, defaultBranch: selectedBranchName,
nonFastForwardDisallowed nonFastForwardDisallowed,
}; };
this.setState({ this.setState({
submitPending: true submitPending: true,
}); });
const configurationLink = repository._links.configuration as Link; const configurationLink = repository._links.configuration as Link;
apiClient apiClient
@@ -160,12 +160,12 @@ class RepositoryConfig extends React.Component<Props, State> {
this.setState({ this.setState({
submitPending: false, submitPending: false,
changesSubmitted: true, changesSubmitted: true,
changed: false changed: false,
}) })
) )
.catch(error => .catch((error) =>
this.setState({ this.setState({
error error,
}) })
); );
}; };
@@ -233,7 +233,7 @@ class RepositoryConfig extends React.Component<Props, State> {
onClick={() => onClick={() =>
this.setState({ this.setState({
changesSubmitted: false, changesSubmitted: false,
changed: false changed: false,
}) })
} }
/> />

View File

@@ -31,14 +31,14 @@ describe("test git predicate", () => {
expect(gitPredicate({})).toBe(false); expect(gitPredicate({})).toBe(false);
expect( expect(
gitPredicate({ gitPredicate({
repository: {} repository: {},
}) })
).toBe(false); ).toBe(false);
expect( expect(
gitPredicate({ gitPredicate({
repository: { repository: {
type: "hg" type: "hg",
} },
}) })
).toBe(false); ).toBe(false);
}); });
@@ -47,8 +47,8 @@ describe("test git predicate", () => {
expect( expect(
gitPredicate({ gitPredicate({
repository: { repository: {
type: "git" type: "git",
} },
}) })
).toBe(true); ).toBe(true);
}); });

View File

@@ -50,7 +50,7 @@ class HgConfigurationForm extends React.Component<Props, State> {
super(props); super(props);
this.state = { this.state = {
...props.initialConfiguration, ...props.initialConfiguration,
validationErrors: [] validationErrors: [],
}; };
} }
@@ -66,7 +66,7 @@ class HgConfigurationForm extends React.Component<Props, State> {
} }
this.setState({ this.setState({
validationErrors validationErrors,
}); });
return validationErrors.length === 0; return validationErrors.length === 0;
@@ -83,7 +83,7 @@ class HgConfigurationForm extends React.Component<Props, State> {
this.setState( this.setState(
// @ts-ignore // @ts-ignore
{ {
[name]: value [name]: value,
}, },
() => this.props.onConfigurationChange(this.state, this.updateValidationStatus()) () => this.props.onConfigurationChange(this.state, this.updateValidationStatus())
); );
@@ -99,7 +99,7 @@ class HgConfigurationForm extends React.Component<Props, State> {
.then(() => .then(() =>
apiClient apiClient
.get((this.props.initialConfiguration._links.self as Link).href) .get((this.props.initialConfiguration._links.self as Link).href)
.then(r => r.json()) .then((r) => r.json())
.then((config: Configuration) => this.setState({ hgBinary: config.hgBinary })) .then((config: Configuration) => this.setState({ hgBinary: config.hgBinary }))
) )
.then(() => this.updateValidationStatus()); .then(() => this.updateValidationStatus());

View File

@@ -52,7 +52,7 @@ const HgRepositoryConfigurationForm: FC<Props> = ({ repository }) => {
const encoding = value ? value : undefined; const encoding = value ? value : undefined;
setConfiguration({ setConfiguration({
...configuration, ...configuration,
encoding encoding,
}); });
}; };

View File

@@ -41,11 +41,11 @@ export const useHgRepositoryConfiguration = (repository: Repository) => {
setLoading(true); setLoading(true);
apiClient apiClient
.get(link) .get(link)
.then(response => response.json()) .then((response) => response.json())
.then((config: HgRepositoryConfiguration) => { .then((config: HgRepositoryConfiguration) => {
setData(config); setData(config);
}) })
.catch(e => setError(e)) .catch((e) => setError(e))
.finally(() => setLoading(false)); .finally(() => setLoading(false));
} }
}, [link]); }, [link]);
@@ -53,7 +53,7 @@ export const useHgRepositoryConfiguration = (repository: Repository) => {
return { return {
isLoading, isLoading,
error, error,
data data,
}; };
}; };
@@ -73,7 +73,7 @@ export const useUpdateHgRepositoryConfiguration = () => {
apiClient apiClient
.put(link, configuration, "application/vnd.scmm-hgConfig-repo+json;v=2") .put(link, configuration, "application/vnd.scmm-hgConfig-repo+json;v=2")
.then(() => setUpdated(true)) .then(() => setUpdated(true))
.catch(e => setError(e)) .catch((e) => setError(e))
.finally(() => setLoading(false)); .finally(() => setLoading(false));
}; };
@@ -81,6 +81,6 @@ export const useUpdateHgRepositoryConfiguration = () => {
isLoading, isLoading,
error, error,
update, update,
updated updated,
}; };
}; };

View File

@@ -45,7 +45,7 @@ class SvnConfigurationForm extends React.Component<Props, State> {
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
this.state = { this.state = {
...props.initialConfiguration ...props.initialConfiguration,
}; };
} }
@@ -56,7 +56,7 @@ class SvnConfigurationForm extends React.Component<Props, State> {
this.setState( this.setState(
// @ts-ignore // @ts-ignore
{ {
[name]: value [name]: value,
}, },
() => this.props.onConfigurationChange(this.state, true) () => this.props.onConfigurationChange(this.state, true)
); );
@@ -73,7 +73,7 @@ class SvnConfigurationForm extends React.Component<Props, State> {
compatibilityOption = (value: string) => { compatibilityOption = (value: string) => {
return { return {
value, value,
label: this.props.t("scm-svn-plugin.config.compatibility-values." + value.toLowerCase()) label: this.props.t("scm-svn-plugin.config.compatibility-values." + value.toLowerCase()),
}; };
}; };

View File

@@ -36,7 +36,7 @@ describe("ApiProvider tests", () => {
it("should register QueryClient", () => { it("should register QueryClient", () => {
const { result } = renderHook(() => useQueryClient(), { const { result } = renderHook(() => useQueryClient(), {
wrapper: createWrapper() wrapper: createWrapper(),
}); });
expect(result.current).toBeDefined(); expect(result.current).toBeDefined();
}); });
@@ -48,7 +48,7 @@ describe("ApiProvider tests", () => {
}; };
const { result } = renderHook(() => useLegacyContext(), { const { result } = renderHook(() => useLegacyContext(), {
wrapper: createWrapper({ onIndexFetched }) wrapper: createWrapper({ onIndexFetched }),
}); });
if (result.current?.onIndexFetched) { if (result.current?.onIndexFetched) {

View File

@@ -31,9 +31,9 @@ import { reset } from "./reset";
const queryClient = new QueryClient({ const queryClient = new QueryClient({
defaultOptions: { defaultOptions: {
queries: { queries: {
retry: false retry: false,
} },
} },
}); });
type Props = LegacyContext & { type Props = LegacyContext & {

View File

@@ -34,7 +34,7 @@ describe("LegacyContext tests", () => {
it("should return provided context", () => { it("should return provided context", () => {
const { result } = renderHook(() => useLegacyContext(), { const { result } = renderHook(() => useLegacyContext(), {
wrapper: createWrapper() wrapper: createWrapper(),
}); });
expect(result.current).toBeDefined(); expect(result.current).toBeDefined();
}); });

View File

@@ -35,7 +35,7 @@ describe("Test admin hooks", () => {
it("should get update info", async () => { it("should get update info", async () => {
const updateInfo: UpdateInfo = { const updateInfo: UpdateInfo = {
latestVersion: "x.y.z", latestVersion: "x.y.z",
link: "http://heartofgold@hitchhiker.com/x.y.z" link: "http://heartofgold@hitchhiker.com/x.y.z",
}; };
fetchMock.getOnce("/api/v2/updateInfo", updateInfo); fetchMock.getOnce("/api/v2/updateInfo", updateInfo);
@@ -43,7 +43,7 @@ describe("Test admin hooks", () => {
setIndexLink(queryClient, "updateInfo", "/updateInfo"); setIndexLink(queryClient, "updateInfo", "/updateInfo");
const { result, waitFor } = renderHook(() => useUpdateInfo(), { const { result, waitFor } = renderHook(() => useUpdateInfo(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => { await waitFor(() => {
return !!result.current.data; return !!result.current.data;

View File

@@ -45,9 +45,9 @@ describe("error handling tests", () => {
context: [ context: [
{ {
type: "planet", type: "planet",
id: "earth" id: "earth",
} },
] ],
}; };
afterEach(() => { afterEach(() => {
@@ -55,9 +55,9 @@ describe("error handling tests", () => {
fetchMock.restore(); fetchMock.restore();
}); });
it("should create a normal error, if the content type is not scmm-error", done => { it("should create a normal error, if the content type is not scmm-error", (done) => {
fetchMock.getOnce("/api/v2/error", { fetchMock.getOnce("/api/v2/error", {
status: 404 status: 404,
}); });
apiClient.get("/error").catch((err: Error) => { apiClient.get("/error").catch((err: Error) => {
@@ -67,13 +67,13 @@ describe("error handling tests", () => {
}); });
}); });
it("should create an backend error, if the content type is scmm-error", done => { it("should create an backend error, if the content type is scmm-error", (done) => {
fetchMock.getOnce("/api/v2/error", { fetchMock.getOnce("/api/v2/error", {
status: 404, status: 404,
headers: { headers: {
"Content-Type": "application/vnd.scmm-error+json;v=2" "Content-Type": "application/vnd.scmm-error+json;v=2",
}, },
body: earthNotFoundError body: earthNotFoundError,
}); });
apiClient.get("/error").catch((err: BackendError) => { apiClient.get("/error").catch((err: BackendError) => {
@@ -87,8 +87,8 @@ describe("error handling tests", () => {
expect(err.context).toEqual([ expect(err.context).toEqual([
{ {
type: "planet", type: "planet",
id: "earth" id: "earth",
} },
]); ]);
done(); done();
}); });

View File

@@ -30,7 +30,7 @@ import {
isBackendError, isBackendError,
TOKEN_EXPIRED_ERROR_CODE, TOKEN_EXPIRED_ERROR_CODE,
TokenExpiredError, TokenExpiredError,
UnauthorizedError UnauthorizedError,
} from "./errors"; } from "./errors";
type SubscriptionEvent = { type SubscriptionEvent = {
@@ -62,12 +62,7 @@ type SubscriptionArgument = MessageListeners | SubscriptionContext;
type Cancel = () => void; type Cancel = () => void;
const sessionId = ( const sessionId = (Date.now().toString(36) + Math.random().toString(36).substr(2, 5)).toUpperCase();
Date.now().toString(36) +
Math.random()
.toString(36)
.substr(2, 5)
).toUpperCase();
const extractXsrfTokenFromJwt = (jwt: string) => { const extractXsrfTokenFromJwt = (jwt: string) => {
const parts = jwt.split("."); const parts = jwt.split(".");
@@ -102,7 +97,7 @@ const createRequestHeaders = () => {
// identify the web interface // identify the web interface
"X-SCM-Client": "WUI", "X-SCM-Client": "WUI",
// identify the window session // identify the window session
"X-SCM-Session-ID": sessionId "X-SCM-Session-ID": sessionId,
}; };
const xsrf = extractXsrfToken(); const xsrf = extractXsrfToken();
@@ -112,10 +107,10 @@ const createRequestHeaders = () => {
return headers; return headers;
}; };
const applyFetchOptions: (p: RequestInit) => RequestInit = o => { const applyFetchOptions: (p: RequestInit) => RequestInit = (o) => {
if (o.headers) { if (o.headers) {
o.headers = { o.headers = {
...createRequestHeaders() ...createRequestHeaders(),
}; };
} else { } else {
o.headers = createRequestHeaders(); o.headers = createRequestHeaders();
@@ -174,9 +169,7 @@ class ApiClient {
requestListeners: RequestListener[] = []; requestListeners: RequestListener[] = [];
get = (url: string): Promise<Response> => { get = (url: string): Promise<Response> => {
return this.request(url, applyFetchOptions({})) return this.request(url, applyFetchOptions({})).then(handleFailure).catch(this.notifyAndRethrow);
.then(handleFailure)
.catch(this.notifyAndRethrow);
}; };
post = ( post = (
@@ -203,7 +196,7 @@ class ApiClient {
const options: RequestInit = { const options: RequestInit = {
method: "POST", method: "POST",
body: formData, body: formData,
headers: additionalHeaders headers: additionalHeaders,
}; };
return this.httpRequestWithBinaryBody(options, url); return this.httpRequestWithBinaryBody(options, url);
}; };
@@ -214,22 +207,18 @@ class ApiClient {
head = (url: string) => { head = (url: string) => {
let options: RequestInit = { let options: RequestInit = {
method: "HEAD" method: "HEAD",
}; };
options = applyFetchOptions(options); options = applyFetchOptions(options);
return this.request(url, options) return this.request(url, options).then(handleFailure).catch(this.notifyAndRethrow);
.then(handleFailure)
.catch(this.notifyAndRethrow);
}; };
delete = (url: string): Promise<Response> => { delete = (url: string): Promise<Response> => {
let options: RequestInit = { let options: RequestInit = {
method: "DELETE" method: "DELETE",
}; };
options = applyFetchOptions(options); options = applyFetchOptions(options);
return this.request(url, options) return this.request(url, options).then(handleFailure).catch(this.notifyAndRethrow);
.then(handleFailure)
.catch(this.notifyAndRethrow);
}; };
httpRequestWithJSONBody = ( httpRequestWithJSONBody = (
@@ -241,7 +230,7 @@ class ApiClient {
): Promise<Response> => { ): Promise<Response> => {
const options: RequestInit = { const options: RequestInit = {
method: method, method: method,
headers: additionalHeaders headers: additionalHeaders,
}; };
if (payload) { if (payload) {
options.body = JSON.stringify(payload); options.body = JSON.stringify(payload);
@@ -257,7 +246,7 @@ class ApiClient {
) => { ) => {
const options: RequestInit = { const options: RequestInit = {
method: method, method: method,
headers: additionalHeaders headers: additionalHeaders,
}; };
options.body = payload; options.body = payload;
return this.httpRequestWithBinaryBody(options, url, "text/plain"); return this.httpRequestWithBinaryBody(options, url, "text/plain");
@@ -273,14 +262,12 @@ class ApiClient {
options.headers["Content-Type"] = contentType; options.headers["Content-Type"] = contentType;
} }
return this.request(url, options) return this.request(url, options).then(handleFailure).catch(this.notifyAndRethrow);
.then(handleFailure)
.catch(this.notifyAndRethrow);
}; };
subscribe(url: string, argument: SubscriptionArgument): Cancel { subscribe(url: string, argument: SubscriptionArgument): Cancel {
const es = new EventSource(createUrlWithIdentifiers(url), { const es = new EventSource(createUrlWithIdentifiers(url), {
withCredentials: true withCredentials: true,
}); });
let listeners: MessageListeners; let listeners: MessageListeners;
@@ -321,11 +308,11 @@ class ApiClient {
}; };
private notifyRequestListeners = (url: string, options: RequestInit) => { private notifyRequestListeners = (url: string, options: RequestInit) => {
this.requestListeners.forEach(requestListener => requestListener(url, options)); this.requestListeners.forEach((requestListener) => requestListener(url, options));
}; };
private notifyAndRethrow = (error: Error): never => { private notifyAndRethrow = (error: Error): never => {
this.errorListeners.forEach(errorListener => errorListener(error)); this.errorListeners.forEach((errorListener) => errorListener(error));
throw error; throw error;
}; };
} }

View File

@@ -34,7 +34,7 @@ describe("Test base api hooks", () => {
describe("useIndex tests", () => { describe("useIndex tests", () => {
fetchMock.get("/api/v2/", { fetchMock.get("/api/v2/", {
version: "x.y.z", version: "x.y.z",
_links: {} _links: {},
}); });
it("should return index", async () => { it("should return index", async () => {
@@ -48,9 +48,9 @@ describe("Test base api hooks", () => {
it("should call onIndexFetched of LegacyContext", async () => { it("should call onIndexFetched of LegacyContext", async () => {
let index: IndexResources; let index: IndexResources;
const context: LegacyContext = { const context: LegacyContext = {
onIndexFetched: fetchedIndex => { onIndexFetched: (fetchedIndex) => {
index = fetchedIndex; index = fetchedIndex;
} },
}; };
const { result, waitFor } = renderHook(() => useIndex(), { wrapper: createWrapper(context) }); const { result, waitFor } = renderHook(() => useIndex(), { wrapper: createWrapper(context) });
await waitFor(() => { await waitFor(() => {
@@ -70,10 +70,10 @@ describe("Test base api hooks", () => {
const queryClient = new QueryClient(); const queryClient = new QueryClient();
queryClient.setQueryData("index", { queryClient.setQueryData("index", {
version: "x.y.z", version: "x.y.z",
_links: {} _links: {},
}); });
const { result } = renderHook(() => useIndexLink("spaceships"), { const { result } = renderHook(() => useIndexLink("spaceships"), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
expect(result.current).toBeUndefined(); expect(result.current).toBeUndefined();
}); });
@@ -86,17 +86,17 @@ describe("Test base api hooks", () => {
spaceships: [ spaceships: [
{ {
name: "heartOfGold", name: "heartOfGold",
href: "/spaceships/heartOfGold" href: "/spaceships/heartOfGold",
}, },
{ {
name: "razorCrest", name: "razorCrest",
href: "/spaceships/razorCrest" href: "/spaceships/razorCrest",
} },
] ],
} },
}); });
const { result } = renderHook(() => useIndexLink("spaceships"), { const { result } = renderHook(() => useIndexLink("spaceships"), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
expect(result.current).toBeUndefined(); expect(result.current).toBeUndefined();
}); });
@@ -107,12 +107,12 @@ describe("Test base api hooks", () => {
version: "x.y.z", version: "x.y.z",
_links: { _links: {
spaceships: { spaceships: {
href: "/api/spaceships" href: "/api/spaceships",
} },
} },
}); });
const { result } = renderHook(() => useIndexLink("spaceships"), { const { result } = renderHook(() => useIndexLink("spaceships"), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
expect(result.current).toBe("/api/spaceships"); expect(result.current).toBe("/api/spaceships");
}); });
@@ -130,12 +130,12 @@ describe("Test base api hooks", () => {
version: "x.y.z", version: "x.y.z",
_links: { _links: {
spaceships: { spaceships: {
href: "/api/spaceships" href: "/api/spaceships",
} },
} },
}); });
const { result } = renderHook(() => useIndexLinks(), { const { result } = renderHook(() => useIndexLinks(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
expect((result.current!.spaceships as Link).href).toBe("/api/spaceships"); expect((result.current!.spaceships as Link).href).toBe("/api/spaceships");
}); });
@@ -150,10 +150,10 @@ describe("Test base api hooks", () => {
it("should return version", () => { it("should return version", () => {
const queryClient = new QueryClient(); const queryClient = new QueryClient();
queryClient.setQueryData("index", { queryClient.setQueryData("index", {
version: "x.y.z" version: "x.y.z",
}); });
const { result } = renderHook(() => useVersion(), { const { result } = renderHook(() => useVersion(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
expect(result.current).toBe("x.y.z"); expect(result.current).toBe("x.y.z");
}); });
@@ -164,10 +164,10 @@ describe("Test base api hooks", () => {
const queryClient = new QueryClient(); const queryClient = new QueryClient();
queryClient.setQueryData("index", { queryClient.setQueryData("index", {
version: "x.y.z", version: "x.y.z",
_links: {} _links: {},
}); });
const { result } = renderHook(() => useRequiredIndexLink("spaceships"), { const { result } = renderHook(() => useRequiredIndexLink("spaceships"), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
expect(result.error).toBeDefined(); expect(result.error).toBeDefined();
}); });
@@ -178,12 +178,12 @@ describe("Test base api hooks", () => {
version: "x.y.z", version: "x.y.z",
_links: { _links: {
spaceships: { spaceships: {
href: "/api/spaceships" href: "/api/spaceships",
} },
} },
}); });
const { result } = renderHook(() => useRequiredIndexLink("spaceships"), { const { result } = renderHook(() => useRequiredIndexLink("spaceships"), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
expect(result.current).toBe("/api/spaceships"); expect(result.current).toBe("/api/spaceships");
}); });
@@ -196,19 +196,19 @@ describe("Test base api hooks", () => {
version: "x.y.z", version: "x.y.z",
_links: { _links: {
spaceships: { spaceships: {
href: "/spaceships" href: "/spaceships",
} },
} },
}); });
const spaceship = { const spaceship = {
name: "heartOfGold" name: "heartOfGold",
}; };
fetchMock.get("/api/v2/spaceships", spaceship); fetchMock.get("/api/v2/spaceships", spaceship);
const { result, waitFor } = renderHook(() => useIndexJsonResource<typeof spaceship>("spaceships"), { const { result, waitFor } = renderHook(() => useIndexJsonResource<typeof spaceship>("spaceships"), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => { await waitFor(() => {
@@ -223,11 +223,11 @@ describe("Test base api hooks", () => {
const queryClient = new QueryClient(); const queryClient = new QueryClient();
queryClient.setQueryData("index", { queryClient.setQueryData("index", {
version: "x.y.z", version: "x.y.z",
_links: {} _links: {},
}); });
const { result } = renderHook(() => useIndexJsonResource<{}>("spaceships"), { const { result } = renderHook(() => useIndexJsonResource<{}>("spaceships"), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
expect(result.current.isLoading).toBe(false); expect(result.current.isLoading).toBe(false);

View File

@@ -60,9 +60,9 @@ describe("Test config hooks", () => {
skipFailedAuthenticators: false, skipFailedAuthenticators: false,
_links: { _links: {
update: { update: {
href: "/config" href: "/config",
} },
} },
}; };
afterEach(() => { afterEach(() => {
@@ -75,7 +75,7 @@ describe("Test config hooks", () => {
setIndexLink(queryClient, "config", "/config"); setIndexLink(queryClient, "config", "/config");
fetchMock.get("/api/v2/config", config); fetchMock.get("/api/v2/config", config);
const { result, waitFor } = renderHook(() => useConfig(), { const { result, waitFor } = renderHook(() => useConfig(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(config); expect(result.current.data).toEqual(config);
@@ -89,15 +89,15 @@ describe("Test config hooks", () => {
const newConfig = { const newConfig = {
...config, ...config,
baseUrl: "/hog" baseUrl: "/hog",
}; };
fetchMock.putOnce("/api/v2/config", { fetchMock.putOnce("/api/v2/config", {
status: 200 status: 200,
}); });
const { result, waitForNextUpdate } = renderHook(() => useUpdateConfig(), { const { result, waitForNextUpdate } = renderHook(() => useUpdateConfig(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {

View File

@@ -30,20 +30,20 @@ import { requiredLink } from "./links";
export const useConfig = (): ApiResult<Config> => { export const useConfig = (): ApiResult<Config> => {
const indexLink = useIndexLink("config"); const indexLink = useIndexLink("config");
return useQuery<Config, Error>("config", () => apiClient.get(indexLink!).then(response => response.json()), { return useQuery<Config, Error>("config", () => apiClient.get(indexLink!).then((response) => response.json()), {
enabled: !!indexLink enabled: !!indexLink,
}); });
}; };
export const useUpdateConfig = () => { export const useUpdateConfig = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { mutate, isLoading, error, data, reset } = useMutation<unknown, Error, Config>( const { mutate, isLoading, error, data, reset } = useMutation<unknown, Error, Config>(
config => { (config) => {
const updateUrl = requiredLink(config, "update"); const updateUrl = requiredLink(config, "update");
return apiClient.put(updateUrl, config, "application/vnd.scmm-config+json;v=2"); return apiClient.put(updateUrl, config, "application/vnd.scmm-config+json;v=2");
}, },
{ {
onSuccess: () => queryClient.invalidateQueries("config") onSuccess: () => queryClient.invalidateQueries("config"),
} }
); );
return { return {
@@ -51,6 +51,6 @@ export const useUpdateConfig = () => {
isLoading, isLoading,
error, error,
isUpdated: !!data, isUpdated: !!data,
reset reset,
}; };
}; };

View File

@@ -50,26 +50,25 @@ describe("Test diff", () => {
content: "0", content: "0",
type: "insert", type: "insert",
lineNumber: 1, lineNumber: 1,
isInsert: true isInsert: true,
} },
] ],
} },
], ],
_links: { _links: {
lines: { lines: {
href: href: "/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/0.txt?start={start}&end={end}",
"/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/0.txt?start={start}&end={end}", templated: true,
templated: true },
} },
} },
}
], ],
partial: false, partial: false,
_links: { _links: {
self: { self: {
href: "/api/v2/diff" href: "/api/v2/diff",
} },
} },
}; };
const partialDiff1: Diff = { const partialDiff1: Diff = {
@@ -93,29 +92,28 @@ describe("Test diff", () => {
content: "0", content: "0",
type: "insert", type: "insert",
lineNumber: 1, lineNumber: 1,
isInsert: true isInsert: true,
} },
] ],
} },
], ],
_links: { _links: {
lines: { lines: {
href: href: "/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/0.txt?start={start}&end={end}",
"/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/0.txt?start={start}&end={end}", templated: true,
templated: true },
} },
} },
}
], ],
partial: true, partial: true,
_links: { _links: {
self: { self: {
href: "/diff" href: "/diff",
}, },
next: { next: {
href: "/diff?offset=1&limit=1" href: "/diff?offset=1&limit=1",
} },
} },
}; };
const partialDiff2: Diff = { const partialDiff2: Diff = {
@@ -139,26 +137,25 @@ describe("Test diff", () => {
content: "1", content: "1",
type: "insert", type: "insert",
lineNumber: 1, lineNumber: 1,
isInsert: true isInsert: true,
} },
] ],
} },
], ],
_links: { _links: {
lines: { lines: {
href: href: "/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/1.txt?start={start}&end={end}",
"/api/v2/repositories/scmadmin/HeartOfGold-git/content/one_to_onehundred/1.txt?start={start}&end={end}", templated: true,
templated: true },
} },
} },
}
], ],
partial: false, partial: false,
_links: { _links: {
self: { self: {
href: "/diff" href: "/diff",
} },
} },
}; };
beforeEach(() => { beforeEach(() => {
@@ -168,10 +165,10 @@ describe("Test diff", () => {
it("should return simple parsed diff", async () => { it("should return simple parsed diff", async () => {
fetchMock.getOnce("/api/v2/diff", { fetchMock.getOnce("/api/v2/diff", {
body: simpleDiff, body: simpleDiff,
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" } headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" },
}); });
const { result, waitFor } = renderHook(() => useDiff("/diff"), { const { result, waitFor } = renderHook(() => useDiff("/diff"), {
wrapper: createWrapper() wrapper: createWrapper(),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(simpleDiff); expect(result.current.data).toEqual(simpleDiff);
@@ -188,10 +185,10 @@ describe("Test diff", () => {
+i am new! +i am new!
\\ No newline at end of file \\ No newline at end of file
`, `,
headers: { "Content-Type": "text/plain" } headers: { "Content-Type": "text/plain" },
}); });
const { result, waitFor } = renderHook(() => useDiff("/diff"), { const { result, waitFor } = renderHook(() => useDiff("/diff"), {
wrapper: createWrapper() wrapper: createWrapper(),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data?.files).toHaveLength(1); expect(result.current.data?.files).toHaveLength(1);
@@ -200,14 +197,14 @@ describe("Test diff", () => {
it("should return parsed diff in multiple chunks", async () => { it("should return parsed diff in multiple chunks", async () => {
fetchMock.getOnce("/api/v2/diff?limit=1", { fetchMock.getOnce("/api/v2/diff?limit=1", {
body: partialDiff1, body: partialDiff1,
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" } headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" },
}); });
fetchMock.getOnce("/api/v2/diff?offset=1&limit=1", { fetchMock.getOnce("/api/v2/diff?offset=1&limit=1", {
body: partialDiff2, body: partialDiff2,
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" } headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" },
}); });
const { result, waitFor, waitForNextUpdate } = renderHook(() => useDiff("/diff?limit=1"), { const { result, waitFor, waitForNextUpdate } = renderHook(() => useDiff("/diff?limit=1"), {
wrapper: createWrapper() wrapper: createWrapper(),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(partialDiff1); expect(result.current.data).toEqual(partialDiff1);
@@ -226,10 +223,10 @@ describe("Test diff", () => {
it("should append query parameters to url which has already query params", async () => { it("should append query parameters to url which has already query params", async () => {
fetchMock.getOnce("/api/v2/diff?format=GIT&limit=25", { fetchMock.getOnce("/api/v2/diff?format=GIT&limit=25", {
body: simpleDiff, body: simpleDiff,
headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" } headers: { "Content-Type": "application/vnd.scmm-diffparsed+json;v=2" },
}); });
const { result, waitFor } = renderHook(() => useDiff("/diff?format=GIT", { limit: 25 }), { const { result, waitFor } = renderHook(() => useDiff("/diff?format=GIT", { limit: 25 }), {
wrapper: createWrapper() wrapper: createWrapper(),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(simpleDiff); expect(result.current.data).toEqual(simpleDiff);

View File

@@ -32,10 +32,10 @@ describe("test createBackendError", () => {
context: [ context: [
{ {
type: "planet", type: "planet",
id: "earth" id: "earth",
} },
], ],
violations: [] violations: [],
}; };
it("should return a default backend error", () => { it("should return a default backend error", () => {

View File

@@ -40,21 +40,21 @@ describe("Test group hooks", () => {
type: "xml", type: "xml",
_links: { _links: {
delete: { delete: {
href: "/groups/jedis" href: "/groups/jedis",
}, },
update: { update: {
href: "/groups/jedis" href: "/groups/jedis",
} },
}, },
_embedded: { _embedded: {
members: [] members: [],
} },
}; };
const jedisCollection = { const jedisCollection = {
_embedded: { _embedded: {
groups: [jedis] groups: [jedis],
} },
}; };
afterEach(() => { afterEach(() => {
@@ -67,7 +67,7 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups"); setIndexLink(queryClient, "groups", "/groups");
fetchMock.get("/api/v2/groups", jedisCollection); fetchMock.get("/api/v2/groups", jedisCollection);
const { result, waitFor } = renderHook(() => useGroups(), { const { result, waitFor } = renderHook(() => useGroups(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(jedisCollection); expect(result.current.data).toEqual(jedisCollection);
@@ -78,11 +78,11 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups"); setIndexLink(queryClient, "groups", "/groups");
fetchMock.get("/api/v2/groups", jedisCollection, { fetchMock.get("/api/v2/groups", jedisCollection, {
query: { query: {
page: "42" page: "42",
} },
}); });
const { result, waitFor } = renderHook(() => useGroups({ page: 42 }), { const { result, waitFor } = renderHook(() => useGroups({ page: 42 }), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(jedisCollection); expect(result.current.data).toEqual(jedisCollection);
@@ -93,11 +93,11 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups"); setIndexLink(queryClient, "groups", "/groups");
fetchMock.get("/api/v2/groups", jedisCollection, { fetchMock.get("/api/v2/groups", jedisCollection, {
query: { query: {
q: "jedis" q: "jedis",
} },
}); });
const { result, waitFor } = renderHook(() => useGroups({ search: "jedis" }), { const { result, waitFor } = renderHook(() => useGroups({ search: "jedis" }), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(jedisCollection); expect(result.current.data).toEqual(jedisCollection);
@@ -108,7 +108,7 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups"); setIndexLink(queryClient, "groups", "/groups");
fetchMock.get("/api/v2/groups", jedisCollection); fetchMock.get("/api/v2/groups", jedisCollection);
const { result, waitFor } = renderHook(() => useGroups(), { const { result, waitFor } = renderHook(() => useGroups(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(queryClient.getQueryData(["group", "jedis"])).toEqual(jedis); expect(queryClient.getQueryData(["group", "jedis"])).toEqual(jedis);
@@ -121,7 +121,7 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups"); setIndexLink(queryClient, "groups", "/groups");
fetchMock.get("/api/v2/groups/jedis", jedis); fetchMock.get("/api/v2/groups/jedis", jedis);
const { result, waitFor } = renderHook(() => useGroup("jedis"), { const { result, waitFor } = renderHook(() => useGroup("jedis"), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(jedis); expect(result.current.data).toEqual(jedis);
@@ -136,14 +136,14 @@ describe("Test group hooks", () => {
fetchMock.postOnce("/api/v2/groups", { fetchMock.postOnce("/api/v2/groups", {
status: 201, status: 201,
headers: { headers: {
Location: "/groups/jedis" Location: "/groups/jedis",
} },
}); });
fetchMock.getOnce("/api/v2/groups/jedis", jedis); fetchMock.getOnce("/api/v2/groups/jedis", jedis);
const { result, waitForNextUpdate } = renderHook(() => useCreateGroup(), { const { result, waitForNextUpdate } = renderHook(() => useCreateGroup(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -160,13 +160,13 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups"); setIndexLink(queryClient, "groups", "/groups");
fetchMock.postOnce("/api/v2/groups", { fetchMock.postOnce("/api/v2/groups", {
status: 201 status: 201,
}); });
fetchMock.getOnce("/api/v2/groups/jedis", jedis); fetchMock.getOnce("/api/v2/groups/jedis", jedis);
const { result, waitForNextUpdate } = renderHook(() => useCreateGroup(), { const { result, waitForNextUpdate } = renderHook(() => useCreateGroup(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -185,11 +185,11 @@ describe("Test group hooks", () => {
setIndexLink(queryClient, "groups", "/groups"); setIndexLink(queryClient, "groups", "/groups");
fetchMock.deleteOnce("/api/v2/groups/jedis", { fetchMock.deleteOnce("/api/v2/groups/jedis", {
status: 200 status: 200,
}); });
const { result, waitForNextUpdate } = renderHook(() => useDeleteGroup(), { const { result, waitForNextUpdate } = renderHook(() => useDeleteGroup(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -212,17 +212,17 @@ describe("Test group hooks", () => {
const newJedis = { const newJedis = {
...jedis, ...jedis,
description: "may the 4th be with you" description: "may the 4th be with you",
}; };
fetchMock.putOnce("/api/v2/groups/jedis", { fetchMock.putOnce("/api/v2/groups/jedis", {
status: 200 status: 200,
}); });
fetchMock.getOnce("/api/v2/groups/jedis", newJedis); fetchMock.getOnce("/api/v2/groups/jedis", newJedis);
const { result, waitForNextUpdate } = renderHook(() => useUpdateGroup(), { const { result, waitForNextUpdate } = renderHook(() => useUpdateGroup(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {

View File

@@ -29,9 +29,9 @@ describe("requireLink tests", () => {
{ {
_links: { _links: {
spaceship: { spaceship: {
href: "/v2/ship" href: "/v2/ship",
} },
} },
}, },
"spaceship" "spaceship"
); );
@@ -49,14 +49,14 @@ describe("requireLink tests", () => {
spaceship: [ spaceship: [
{ {
name: "one", name: "one",
href: "/v2/one" href: "/v2/one",
}, },
{ {
name: "two", name: "two",
href: "/v2/two" href: "/v2/two",
} },
] ],
} },
}; };
expect(() => requiredLink(object, "spaceship")).toThrowError(); expect(() => requiredLink(object, "spaceship")).toThrowError();
}); });
@@ -67,14 +67,14 @@ describe("requireLink tests", () => {
spaceship: [ spaceship: [
{ {
name: "one", name: "one",
href: "/v2/one" href: "/v2/one",
}, },
{ {
name: "two", name: "two",
href: "/v2/two" href: "/v2/two",
} },
] ],
} },
}; };
expect(requiredLink(object, "spaceship", "one")).toBe("/v2/one"); expect(requiredLink(object, "spaceship", "one")).toBe("/v2/one");
}); });
@@ -85,14 +85,14 @@ describe("requireLink tests", () => {
spaceship: [ spaceship: [
{ {
name: "one", name: "one",
href: "/v2/one" href: "/v2/one",
}, },
{ {
name: "two", name: "two",
href: "/v2/two" href: "/v2/two",
} },
] ],
} },
}; };
expect(() => requiredLink(object, "spaceship", "three")).toThrowError(); expect(() => requiredLink(object, "spaceship", "three")).toThrowError();
}); });

View File

@@ -37,7 +37,7 @@ describe("Test login hooks", () => {
name: "tricia", name: "tricia",
displayName: "Tricia", displayName: "Tricia",
groups: [], groups: [],
_links: {} _links: {},
}; };
describe("useMe tests", () => { describe("useMe tests", () => {
@@ -45,7 +45,7 @@ describe("Test login hooks", () => {
name: "tricia", name: "tricia",
displayName: "Tricia", displayName: "Tricia",
groups: [], groups: [],
_links: {} _links: {},
}); });
it("should return me", async () => { it("should return me", async () => {
@@ -65,9 +65,9 @@ describe("Test login hooks", () => {
let me: Me; let me: Me;
const context: LegacyContext = { const context: LegacyContext = {
onMeFetched: fetchedMe => { onMeFetched: (fetchedMe) => {
me = fetchedMe; me = fetchedMe;
} },
}; };
const { result, waitFor } = renderHook(() => useMe(), { wrapper: createWrapper(context, queryClient) }); const { result, waitFor } = renderHook(() => useMe(), { wrapper: createWrapper(context, queryClient) });
@@ -130,7 +130,7 @@ describe("Test login hooks", () => {
name: "_anonymous", name: "_anonymous",
displayName: "Anonymous", displayName: "Anonymous",
groups: [], groups: [],
_links: {} _links: {},
}); });
const { result } = renderHook(() => useSubject(), { wrapper: createWrapper(undefined, queryClient) }); const { result } = renderHook(() => useSubject(), { wrapper: createWrapper(undefined, queryClient) });
@@ -158,8 +158,8 @@ describe("Test login hooks", () => {
cookie: true, cookie: true,
grant_type: "password", grant_type: "password",
username: "tricia", username: "tricia",
password: "hitchhikersSecret!" password: "hitchhikersSecret!",
} },
}); });
// required because we invalidate the whole cache and react-query refetches the index // required because we invalidate the whole cache and react-query refetches the index
@@ -167,13 +167,13 @@ describe("Test login hooks", () => {
version: "x.y.z", version: "x.y.z",
_links: { _links: {
login: { login: {
href: "/second/login" href: "/second/login",
} },
} },
}); });
const { result, waitForNextUpdate } = renderHook(() => useLogin(), { const { result, waitForNextUpdate } = renderHook(() => useLogin(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
const { login } = result.current; const { login } = result.current;
expect(login).toBeDefined(); expect(login).toBeDefined();
@@ -194,7 +194,7 @@ describe("Test login hooks", () => {
queryClient.setQueryData("me", tricia); queryClient.setQueryData("me", tricia);
const { result } = renderHook(() => useLogin(), { const { result } = renderHook(() => useLogin(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
expect(result.current.login).toBeUndefined(); expect(result.current.login).toBeUndefined();
@@ -209,7 +209,7 @@ describe("Test login hooks", () => {
fetchMock.deleteOnce("/api/v2/logout", {}); fetchMock.deleteOnce("/api/v2/logout", {});
const { result, waitForNextUpdate } = renderHook(() => useLogout(), { const { result, waitForNextUpdate } = renderHook(() => useLogout(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
const { logout } = result.current; const { logout } = result.current;
expect(logout).toBeDefined(); expect(logout).toBeDefined();
@@ -229,7 +229,7 @@ describe("Test login hooks", () => {
setEmptyIndex(queryClient); setEmptyIndex(queryClient);
const { result } = renderHook(() => useLogout(), { const { result } = renderHook(() => useLogout(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
const { logout } = result.current; const { logout } = result.current;

View File

@@ -32,13 +32,13 @@ import { useReset } from "./reset";
export const useMe = (): ApiResult<Me> => { export const useMe = (): ApiResult<Me> => {
const legacy = useLegacyContext(); const legacy = useLegacyContext();
const link = useIndexLink("me"); const link = useIndexLink("me");
return useQuery<Me, Error>("me", () => apiClient.get(link!).then(response => response.json()), { return useQuery<Me, Error>("me", () => apiClient.get(link!).then((response) => response.json()), {
enabled: !!link, enabled: !!link,
onSuccess: me => { onSuccess: (me) => {
if (legacy.onMeFetched) { if (legacy.onMeFetched) {
legacy.onMeFetched(me); legacy.onMeFetched(me);
} }
} },
}); });
}; };
@@ -60,7 +60,7 @@ export const useSubject = () => {
isAnonymous, isAnonymous,
isLoading, isLoading,
error, error,
me me,
}; };
}; };
@@ -75,9 +75,9 @@ export const useLogin = () => {
const link = useIndexLink("login"); const link = useIndexLink("login");
const reset = useReset(); const reset = useReset();
const { mutate, isLoading, error } = useMutation<unknown, Error, Credentials>( const { mutate, isLoading, error } = useMutation<unknown, Error, Credentials>(
credentials => apiClient.post(link!, credentials), (credentials) => apiClient.post(link!, credentials),
{ {
onSuccess: reset onSuccess: reset,
} }
); );
@@ -91,7 +91,7 @@ export const useLogin = () => {
return { return {
login: link ? login : undefined, login: link ? login : undefined,
isLoading, isLoading,
error error,
}; };
}; };
@@ -104,14 +104,14 @@ export const useLogout = () => {
const reset = useReset(); const reset = useReset();
const { mutate, isLoading, error, data } = useMutation<LogoutResponse, Error, unknown>( const { mutate, isLoading, error, data } = useMutation<LogoutResponse, Error, unknown>(
() => apiClient.delete(link!).then(r => (r.status === 200 ? r.json() : {})), () => apiClient.delete(link!).then((r) => (r.status === 200 ? r.json() : {})),
{ {
onSuccess: response => { onSuccess: (response) => {
if (response?.logoutRedirect) { if (response?.logoutRedirect) {
window.location.assign(response.logoutRedirect); window.location.assign(response.logoutRedirect);
} }
return reset(); return reset();
} },
} }
); );
@@ -122,6 +122,6 @@ export const useLogout = () => {
return { return {
logout: link && !data ? logout : undefined, logout: link && !data ? logout : undefined,
isLoading, isLoading,
error error,
}; };
}; };

View File

@@ -38,14 +38,14 @@ describe("Test namespace hooks", () => {
namespaces: [ namespaces: [
{ {
namespace: "spaceships", namespace: "spaceships",
_links: {} _links: {},
} },
] ],
} },
}); });
const { result, waitFor } = renderHook(() => useNamespaces(), { const { result, waitFor } = renderHook(() => useNamespaces(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => { await waitFor(() => {
return !!result.current.data; return !!result.current.data;
@@ -61,11 +61,11 @@ describe("Test namespace hooks", () => {
fetchMock.get("/api/v2/ns", { fetchMock.get("/api/v2/ns", {
current: "awesome", current: "awesome",
available: [], available: [],
_links: {} _links: {},
}); });
const { result, waitFor } = renderHook(() => useNamespaceStrategies(), { const { result, waitFor } = renderHook(() => useNamespaceStrategies(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => { await waitFor(() => {
return !!result.current.data; return !!result.current.data;
@@ -80,11 +80,11 @@ describe("Test namespace hooks", () => {
setIndexLink(queryClient, "namespaces", "/ns"); setIndexLink(queryClient, "namespaces", "/ns");
fetchMock.get("/api/v2/ns/awesome", { fetchMock.get("/api/v2/ns/awesome", {
namespace: "awesome", namespace: "awesome",
_links: {} _links: {},
}); });
const { result, waitFor } = renderHook(() => useNamespace("awesome"), { const { result, waitFor } = renderHook(() => useNamespace("awesome"), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => { await waitFor(() => {
return !!result.current.data; return !!result.current.data;

View File

@@ -34,7 +34,7 @@ export const useNamespaces = () => {
export const useNamespace = (name: string): ApiResult<Namespace> => { export const useNamespace = (name: string): ApiResult<Namespace> => {
const namespacesLink = useRequiredIndexLink("namespaces"); const namespacesLink = useRequiredIndexLink("namespaces");
return useQuery<Namespace, Error>(["namespace", name], () => return useQuery<Namespace, Error>(["namespace", name], () =>
apiClient.get(concat(namespacesLink, name)).then(response => response.json()) apiClient.get(concat(namespacesLink, name)).then((response) => response.json())
); );
}; };

View File

@@ -40,26 +40,28 @@ const waitForRestartAfter = (
const endTime = Number(new Date()) + 60000; const endTime = Number(new Date()) + 60000;
let started = false; let started = false;
const executor = <T = any>(data: T) => (resolve: (result: T) => void, reject: (error: Error) => void) => { const executor =
// we need some initial delay <T = any>(data: T) =>
if (!started) { (resolve: (result: T) => void, reject: (error: Error) => void) => {
started = true; // we need some initial delay
setTimeout(executor(data), initialDelay, resolve, reject); if (!started) {
} else { started = true;
apiClient setTimeout(executor(data), initialDelay, resolve, reject);
.get("") } else {
.then(() => resolve(data)) apiClient
.catch(() => { .get("")
if (Number(new Date()) < endTime) { .then(() => resolve(data))
setTimeout(executor(data), timeout, resolve, reject); .catch(() => {
} else { if (Number(new Date()) < endTime) {
reject(new Error("timeout reached")); setTimeout(executor(data), timeout, resolve, reject);
} } else {
}); reject(new Error("timeout reached"));
} }
}; });
}
};
return promise.then(data => new Promise<void>(executor(data))); return promise.then((data) => new Promise<void>(executor(data)));
}; };
export type UseAvailablePluginsOptions = { export type UseAvailablePluginsOptions = {
@@ -70,10 +72,10 @@ export const useAvailablePlugins = ({ enabled }: UseAvailablePluginsOptions = {}
const indexLink = useRequiredIndexLink("availablePlugins"); const indexLink = useRequiredIndexLink("availablePlugins");
return useQuery<PluginCollection, Error>( return useQuery<PluginCollection, Error>(
["plugins", "available"], ["plugins", "available"],
() => apiClient.get(indexLink).then(response => response.json()), () => apiClient.get(indexLink).then((response) => response.json()),
{ {
enabled, enabled,
retry: 3 retry: 3,
} }
); );
}; };
@@ -86,10 +88,10 @@ export const useInstalledPlugins = ({ enabled }: UseInstalledPluginsOptions = {}
const indexLink = useRequiredIndexLink("installedPlugins"); const indexLink = useRequiredIndexLink("installedPlugins");
return useQuery<PluginCollection, Error>( return useQuery<PluginCollection, Error>(
["plugins", "installed"], ["plugins", "installed"],
() => apiClient.get(indexLink).then(response => response.json()), () => apiClient.get(indexLink).then((response) => response.json()),
{ {
enabled, enabled,
retry: 3 retry: 3,
} }
); );
}; };
@@ -98,10 +100,10 @@ export const usePendingPlugins = (): ApiResult<PendingPlugins> => {
const indexLink = useIndexLink("pendingPlugins"); const indexLink = useIndexLink("pendingPlugins");
return useQuery<PendingPlugins, Error>( return useQuery<PendingPlugins, Error>(
["plugins", "pending"], ["plugins", "pending"],
() => apiClient.get(indexLink!).then(response => response.json()), () => apiClient.get(indexLink!).then((response) => response.json()),
{ {
enabled: !!indexLink, enabled: !!indexLink,
retry: 3 retry: 3,
} }
); );
}; };
@@ -133,19 +135,19 @@ export const useInstallPlugin = () => {
return promise; return promise;
}, },
{ {
onSuccess: () => queryClient.invalidateQueries("plugins") onSuccess: () => queryClient.invalidateQueries("plugins"),
} }
); );
return { return {
install: (plugin: Plugin, restartOptions: RestartOptions = {}) => install: (plugin: Plugin, restartOptions: RestartOptions = {}) =>
mutate({ mutate({
plugin, plugin,
restartOptions restartOptions,
}), }),
isLoading, isLoading,
error, error,
data, data,
isInstalled: !!data isInstalled: !!data,
}; };
}; };
@@ -160,18 +162,18 @@ export const useUninstallPlugin = () => {
return promise; return promise;
}, },
{ {
onSuccess: () => queryClient.invalidateQueries("plugins") onSuccess: () => queryClient.invalidateQueries("plugins"),
} }
); );
return { return {
uninstall: (plugin: Plugin, restartOptions: RestartOptions = {}) => uninstall: (plugin: Plugin, restartOptions: RestartOptions = {}) =>
mutate({ mutate({
plugin, plugin,
restartOptions restartOptions,
}), }),
isLoading, isLoading,
error, error,
isUninstalled: !!data isUninstalled: !!data,
}; };
}; };
@@ -194,18 +196,18 @@ export const useUpdatePlugins = () => {
return promise; return promise;
}, },
{ {
onSuccess: () => queryClient.invalidateQueries("plugins") onSuccess: () => queryClient.invalidateQueries("plugins"),
} }
); );
return { return {
update: (plugin: Plugin | PluginCollection, restartOptions: RestartOptions = {}) => update: (plugin: Plugin | PluginCollection, restartOptions: RestartOptions = {}) =>
mutate({ mutate({
plugins: plugin, plugins: plugin,
restartOptions restartOptions,
}), }),
isLoading, isLoading,
error, error,
isUpdated: !!data isUpdated: !!data,
}; };
}; };
@@ -220,7 +222,7 @@ export const useExecutePendingPlugins = () => {
({ pending, restartOptions }) => ({ pending, restartOptions }) =>
waitForRestartAfter(apiClient.post(requiredLink(pending, "execute")), restartOptions), waitForRestartAfter(apiClient.post(requiredLink(pending, "execute")), restartOptions),
{ {
onSuccess: () => queryClient.invalidateQueries("plugins") onSuccess: () => queryClient.invalidateQueries("plugins"),
} }
); );
return { return {
@@ -228,22 +230,22 @@ export const useExecutePendingPlugins = () => {
mutate({ pending, restartOptions }), mutate({ pending, restartOptions }),
isLoading, isLoading,
error, error,
isExecuted: !!data isExecuted: !!data,
}; };
}; };
export const useCancelPendingPlugins = () => { export const useCancelPendingPlugins = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { mutate, isLoading, error, data } = useMutation<unknown, Error, PendingPlugins>( const { mutate, isLoading, error, data } = useMutation<unknown, Error, PendingPlugins>(
pending => apiClient.post(requiredLink(pending, "cancel")), (pending) => apiClient.post(requiredLink(pending, "cancel")),
{ {
onSuccess: () => queryClient.invalidateQueries("plugins") onSuccess: () => queryClient.invalidateQueries("plugins"),
} }
); );
return { return {
update: (pending: PendingPlugins) => mutate(pending), update: (pending: PendingPlugins) => mutate(pending),
isLoading, isLoading,
error, error,
isCancelled: !!data isCancelled: !!data,
}; };
}; };

View File

@@ -32,8 +32,9 @@ import { act } from "react-test-renderer";
import { import {
useCreateRepositoryRole, useCreateRepositoryRole,
useDeleteRepositoryRole, useDeleteRepositoryRole,
useRepositoryRole, useRepositoryRoles, useRepositoryRole,
useUpdateRepositoryRole useRepositoryRoles,
useUpdateRepositoryRole,
} from "./repository-roles"; } from "./repository-roles";
describe("Test repository-roles hooks", () => { describe("Test repository-roles hooks", () => {
@@ -43,12 +44,12 @@ describe("Test repository-roles hooks", () => {
verbs: ["rocking"], verbs: ["rocking"],
_links: { _links: {
delete: { delete: {
href: "/repositoryRoles/theroleingstones" href: "/repositoryRoles/theroleingstones",
}, },
update: { update: {
href: "/repositoryRoles/theroleingstones" href: "/repositoryRoles/theroleingstones",
} },
} },
}; };
const roleCollection: RepositoryRoleCollection = { const roleCollection: RepositoryRoleCollection = {
@@ -56,8 +57,8 @@ describe("Test repository-roles hooks", () => {
pageTotal: 0, pageTotal: 0,
_links: {}, _links: {},
_embedded: { _embedded: {
repositoryRoles: [role] repositoryRoles: [role],
} },
}; };
afterEach(() => { afterEach(() => {
@@ -70,7 +71,7 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles"); setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.get("/api/v2/repositoryRoles", roleCollection); fetchMock.get("/api/v2/repositoryRoles", roleCollection);
const { result, waitFor } = renderHook(() => useRepositoryRoles(), { const { result, waitFor } = renderHook(() => useRepositoryRoles(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(roleCollection); expect(result.current.data).toEqual(roleCollection);
@@ -81,11 +82,11 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles"); setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.get("/api/v2/repositoryRoles", roleCollection, { fetchMock.get("/api/v2/repositoryRoles", roleCollection, {
query: { query: {
page: "42" page: "42",
} },
}); });
const { result, waitFor } = renderHook(() => useRepositoryRoles({ page: 42 }), { const { result, waitFor } = renderHook(() => useRepositoryRoles({ page: 42 }), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(roleCollection); expect(result.current.data).toEqual(roleCollection);
@@ -96,7 +97,7 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles"); setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.get("/api/v2/repositoryRoles", roleCollection); fetchMock.get("/api/v2/repositoryRoles", roleCollection);
const { result, waitFor } = renderHook(() => useRepositoryRoles(), { const { result, waitFor } = renderHook(() => useRepositoryRoles(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(queryClient.getQueryData(["repositoryRole", roleName])).toEqual(role); expect(queryClient.getQueryData(["repositoryRole", roleName])).toEqual(role);
@@ -109,7 +110,7 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles"); setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.get("/api/v2/repositoryRoles/" + roleName, role); fetchMock.get("/api/v2/repositoryRoles/" + roleName, role);
const { result, waitFor } = renderHook(() => useRepositoryRole(roleName), { const { result, waitFor } = renderHook(() => useRepositoryRole(roleName), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(role); expect(result.current.data).toEqual(role);
@@ -124,14 +125,14 @@ describe("Test repository-roles hooks", () => {
fetchMock.postOnce("/api/v2/repositoryRoles", { fetchMock.postOnce("/api/v2/repositoryRoles", {
status: 201, status: 201,
headers: { headers: {
Location: "/repositoryRoles/" + roleName Location: "/repositoryRoles/" + roleName,
} },
}); });
fetchMock.getOnce("/api/v2/repositoryRoles/" + roleName, role); fetchMock.getOnce("/api/v2/repositoryRoles/" + roleName, role);
const { result, waitForNextUpdate } = renderHook(() => useCreateRepositoryRole(), { const { result, waitForNextUpdate } = renderHook(() => useCreateRepositoryRole(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -148,13 +149,13 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles"); setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.postOnce("/api/v2/repositoryRoles", { fetchMock.postOnce("/api/v2/repositoryRoles", {
status: 201 status: 201,
}); });
fetchMock.getOnce("/api/v2/repositoryRoles/" + roleName, role); fetchMock.getOnce("/api/v2/repositoryRoles/" + roleName, role);
const { result, waitForNextUpdate } = renderHook(() => useCreateRepositoryRole(), { const { result, waitForNextUpdate } = renderHook(() => useCreateRepositoryRole(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -173,11 +174,11 @@ describe("Test repository-roles hooks", () => {
setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles"); setIndexLink(queryClient, "repositoryRoles", "/repositoryRoles");
fetchMock.deleteOnce("/api/v2/repositoryRoles/" + roleName, { fetchMock.deleteOnce("/api/v2/repositoryRoles/" + roleName, {
status: 200 status: 200,
}); });
const { result, waitForNextUpdate } = renderHook(() => useDeleteRepositoryRole(), { const { result, waitForNextUpdate } = renderHook(() => useDeleteRepositoryRole(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -200,15 +201,15 @@ describe("Test repository-roles hooks", () => {
const newRole: RepositoryRole = { const newRole: RepositoryRole = {
...role, ...role,
name: "newname" name: "newname",
}; };
fetchMock.putOnce("/api/v2/repositoryRoles/" + roleName, { fetchMock.putOnce("/api/v2/repositoryRoles/" + roleName, {
status: 200 status: 200,
}); });
const { result, waitForNextUpdate } = renderHook(() => useUpdateRepositoryRole(), { const { result, waitForNextUpdate } = renderHook(() => useUpdateRepositoryRole(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {

View File

@@ -25,7 +25,7 @@ import { QueryClient, useQueryClient } from "react-query";
export const reset = (queryClient: QueryClient) => { export const reset = (queryClient: QueryClient) => {
queryClient.removeQueries({ queryClient.removeQueries({
predicate: ({ queryKey }) => queryKey !== "index" predicate: ({ queryKey }) => queryKey !== "index",
}); });
return queryClient.invalidateQueries("index"); return queryClient.invalidateQueries("index");
}; };

View File

@@ -35,9 +35,9 @@ describe("Test sources hooks", () => {
type: "git", type: "git",
_links: { _links: {
sources: { sources: {
href: "/src" href: "/src",
} },
} },
}; };
const readmeMd: File = { const readmeMd: File = {
@@ -49,8 +49,8 @@ describe("Test sources hooks", () => {
description: "Awesome readme", description: "Awesome readme",
_links: {}, _links: {},
_embedded: { _embedded: {
children: [] children: [],
} },
}; };
const rootDirectory: File = { const rootDirectory: File = {
@@ -60,8 +60,8 @@ describe("Test sources hooks", () => {
revision: "abc", revision: "abc",
_links: {}, _links: {},
_embedded: { _embedded: {
children: [readmeMd] children: [readmeMd],
} },
}; };
const sepecialMd: File = { const sepecialMd: File = {
@@ -73,20 +73,20 @@ describe("Test sources hooks", () => {
description: "Awesome special file", description: "Awesome special file",
_links: {}, _links: {},
_embedded: { _embedded: {
children: [] children: [],
} },
}; };
const sepecialMdPartial: File = { const sepecialMdPartial: File = {
...sepecialMd, ...sepecialMd,
partialResult: true, partialResult: true,
computationAborted: false computationAborted: false,
}; };
const sepecialMdComputationAborted: File = { const sepecialMdComputationAborted: File = {
...sepecialMd, ...sepecialMd,
partialResult: true, partialResult: true,
computationAborted: true computationAborted: true,
}; };
const mainDirectoryTruncated: File = { const mainDirectoryTruncated: File = {
@@ -97,20 +97,20 @@ describe("Test sources hooks", () => {
truncated: true, truncated: true,
_links: { _links: {
proceed: { proceed: {
href: "src/2" href: "src/2",
} },
}, },
_embedded: { _embedded: {
children: [] children: [],
} },
}; };
const mainDirectory: File = { const mainDirectory: File = {
...mainDirectoryTruncated, ...mainDirectoryTruncated,
truncated: false, truncated: false,
_embedded: { _embedded: {
children: [sepecialMd] children: [sepecialMd],
} },
}; };
beforeEach(() => { beforeEach(() => {
@@ -128,7 +128,7 @@ describe("Test sources hooks", () => {
const queryClient = createInfiniteCachingClient(); const queryClient = createInfiniteCachingClient();
fetchMock.getOnce("/api/v2/src", rootDirectory); fetchMock.getOnce("/api/v2/src", rootDirectory);
const { result, waitFor } = renderHook(() => useSources(puzzle42), { const { result, waitFor } = renderHook(() => useSources(puzzle42), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(rootDirectory); expect(result.current.data).toEqual(rootDirectory);
@@ -138,7 +138,7 @@ describe("Test sources hooks", () => {
const queryClient = createInfiniteCachingClient(); const queryClient = createInfiniteCachingClient();
fetchMock.getOnce("/api/v2/src/abc/README.md", readmeMd); fetchMock.getOnce("/api/v2/src/abc/README.md", readmeMd);
const { result, waitFor } = renderHook(() => useSources(puzzle42, { revision: "abc", path: "README.md" }), { const { result, waitFor } = renderHook(() => useSources(puzzle42, { revision: "abc", path: "README.md" }), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(readmeMd); expect(result.current.data).toEqual(readmeMd);
@@ -149,7 +149,7 @@ describe("Test sources hooks", () => {
fetchMock.getOnce("/api/v2/src", mainDirectoryTruncated); fetchMock.getOnce("/api/v2/src", mainDirectoryTruncated);
fetchMock.getOnce("/api/v2/src/2", mainDirectory); fetchMock.getOnce("/api/v2/src/2", mainDirectory);
const { result, waitFor, waitForNextUpdate } = renderHook(() => useSources(puzzle42), { const { result, waitFor, waitForNextUpdate } = renderHook(() => useSources(puzzle42), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
@@ -172,11 +172,11 @@ describe("Test sources hooks", () => {
{ {
...mainDirectory, ...mainDirectory,
_embedded: { _embedded: {
children: [sepecialMdPartial] children: [sepecialMdPartial],
} },
}, },
{ {
repeat: 1 repeat: 1,
} }
); );
fetchMock.get( fetchMock.get(
@@ -184,17 +184,17 @@ describe("Test sources hooks", () => {
{ {
...mainDirectory, ...mainDirectory,
_embedded: { _embedded: {
children: [sepecialMd] children: [sepecialMd],
} },
}, },
{ {
repeat: 1, repeat: 1,
overwriteRoutes: false overwriteRoutes: false,
} }
); );
const { result, waitFor } = renderHook(() => useSources(puzzle42, { refetchPartialInterval: 100 }), { const { result, waitFor } = renderHook(() => useSources(puzzle42, { refetchPartialInterval: 100 }), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!firstChild(result.current.data)); await waitFor(() => !!firstChild(result.current.data));
@@ -210,23 +210,23 @@ describe("Test sources hooks", () => {
// should never be called // should never be called
fetchMock.getOnce("/api/v2/src/abc/main/special.md", sepecialMd, { fetchMock.getOnce("/api/v2/src/abc/main/special.md", sepecialMd, {
repeat: 1, repeat: 1,
overwriteRoutes: false overwriteRoutes: false,
}); });
const { result, waitFor } = renderHook( const { result, waitFor } = renderHook(
() => () =>
useSources(puzzle42, { useSources(puzzle42, {
revision: "abc", revision: "abc",
path: "main/special.md", path: "main/special.md",
refetchPartialInterval: 100 refetchPartialInterval: 100,
}), }),
{ {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
} }
); );
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(sepecialMdComputationAborted); expect(result.current.data).toEqual(sepecialMdComputationAborted);
await new Promise(r => setTimeout(r, 200)); await new Promise((r) => setTimeout(r, 200));
expect(result.current.data).toEqual(sepecialMdComputationAborted); expect(result.current.data).toEqual(sepecialMdComputationAborted);
}); });
}); });

View File

@@ -37,25 +37,25 @@ export type UseSourcesOptions = {
const UseSourcesDefaultOptions: UseSourcesOptions = { const UseSourcesDefaultOptions: UseSourcesOptions = {
enabled: true, enabled: true,
refetchPartialInterval: 3000 refetchPartialInterval: 3000,
}; };
export const useSources = (repository: Repository, opts: UseSourcesOptions = UseSourcesDefaultOptions) => { export const useSources = (repository: Repository, opts: UseSourcesOptions = UseSourcesDefaultOptions) => {
const options = { const options = {
...UseSourcesDefaultOptions, ...UseSourcesDefaultOptions,
...opts ...opts,
}; };
const link = createSourcesLink(repository, options); const link = createSourcesLink(repository, options);
const { isLoading, error, data, isFetchingNextPage, fetchNextPage, refetch } = useInfiniteQuery<File, Error, File>( const { isLoading, error, data, isFetchingNextPage, fetchNextPage, refetch } = useInfiniteQuery<File, Error, File>(
repoQueryKey(repository, "sources", options.revision || "", options.path || ""), repoQueryKey(repository, "sources", options.revision || "", options.path || ""),
({ pageParam }) => { ({ pageParam }) => {
return apiClient.get(pageParam || link).then(response => response.json()); return apiClient.get(pageParam || link).then((response) => response.json());
}, },
{ {
enabled: options.enabled, enabled: options.enabled,
getNextPageParam: lastPage => { getNextPageParam: (lastPage) => {
return (lastPage._links.proceed as Link)?.href; return (lastPage._links.proceed as Link)?.href;
} },
} }
); );
@@ -64,7 +64,7 @@ export const useSources = (repository: Repository, opts: UseSourcesOptions = Use
const intervalId = setInterval(() => { const intervalId = setInterval(() => {
if (isPartial(file)) { if (isPartial(file)) {
refetch({ refetch({
throwOnError: true throwOnError: true,
}); });
} }
}, options.refetchPartialInterval); }, options.refetchPartialInterval);
@@ -79,7 +79,7 @@ export const useSources = (repository: Repository, opts: UseSourcesOptions = Use
fetchNextPage: () => { fetchNextPage: () => {
// wrapped because we do not want to leak react-query types in our api // wrapped because we do not want to leak react-query types in our api
fetchNextPage(); fetchNextPage();
} },
}; };
}; };
@@ -108,8 +108,8 @@ const merge = (files?: File[]): File | undefined => {
...lastPage, ...lastPage,
_embedded: { _embedded: {
...lastPage._embedded, ...lastPage._embedded,
children children,
} },
}; };
}; };

View File

@@ -36,9 +36,9 @@ describe("Test Tag hooks", () => {
type: "git", type: "git",
_links: { _links: {
tags: { tags: {
href: "/hog/tags" href: "/hog/tags",
} },
} },
}; };
const changeset: Changeset = { const changeset: Changeset = {
@@ -46,14 +46,14 @@ describe("Test Tag hooks", () => {
description: "Awesome change", description: "Awesome change",
date: new Date(), date: new Date(),
author: { author: {
name: "Arthur Dent" name: "Arthur Dent",
}, },
_embedded: {}, _embedded: {},
_links: { _links: {
tag: { tag: {
href: "/hog/tag" href: "/hog/tag",
} },
} },
}; };
const tagOneDotZero = { const tagOneDotZero = {
@@ -61,17 +61,17 @@ describe("Test Tag hooks", () => {
revision: "42", revision: "42",
signatures: [], signatures: [],
_links: { _links: {
"delete": { delete: {
href: "/hog/tags/1.0" href: "/hog/tags/1.0",
} },
} },
}; };
const tags: TagCollection = { const tags: TagCollection = {
_embedded: { _embedded: {
tags: [tagOneDotZero] tags: [tagOneDotZero],
}, },
_links: {} _links: {},
}; };
const queryClient = createInfiniteCachingClient(); const queryClient = createInfiniteCachingClient();
@@ -87,7 +87,7 @@ describe("Test Tag hooks", () => {
fetchMock.getOnce("/api/v2/hog/tags", tags); fetchMock.getOnce("/api/v2/hog/tags", tags);
const { result, waitFor } = renderHook(() => useTags(repository), { const { result, waitFor } = renderHook(() => useTags(repository), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => { await waitFor(() => {
return !!result.current.data; return !!result.current.data;
@@ -114,7 +114,7 @@ describe("Test Tag hooks", () => {
fetchMock.getOnce("/api/v2/hog/tags/1.0", tagOneDotZero); fetchMock.getOnce("/api/v2/hog/tags/1.0", tagOneDotZero);
const { result, waitFor } = renderHook(() => useTag(repository, "1.0"), { const { result, waitFor } = renderHook(() => useTag(repository, "1.0"), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => { await waitFor(() => {
return !!result.current.data; return !!result.current.data;
@@ -141,14 +141,14 @@ describe("Test Tag hooks", () => {
fetchMock.postOnce("/api/v2/hog/tag", { fetchMock.postOnce("/api/v2/hog/tag", {
status: 201, status: 201,
headers: { headers: {
Location: "/hog/tags/1.0" Location: "/hog/tags/1.0",
} },
}); });
fetchMock.getOnce("/api/v2/hog/tags/1.0", tagOneDotZero); fetchMock.getOnce("/api/v2/hog/tags/1.0", tagOneDotZero);
const { result, waitForNextUpdate } = renderHook(() => useCreateTag(repository, changeset), { const { result, waitForNextUpdate } = renderHook(() => useCreateTag(repository, changeset), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -195,11 +195,11 @@ describe("Test Tag hooks", () => {
it("should fail without location header", async () => { it("should fail without location header", async () => {
fetchMock.postOnce("/api/v2/hog/tag", { fetchMock.postOnce("/api/v2/hog/tag", {
status: 201 status: 201,
}); });
const { result, waitForNextUpdate } = renderHook(() => useCreateTag(repository, changeset), { const { result, waitForNextUpdate } = renderHook(() => useCreateTag(repository, changeset), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -215,11 +215,11 @@ describe("Test Tag hooks", () => {
describe("useDeleteTags tests", () => { describe("useDeleteTags tests", () => {
const deleteTag = async () => { const deleteTag = async () => {
fetchMock.deleteOnce("/api/v2/hog/tags/1.0", { fetchMock.deleteOnce("/api/v2/hog/tags/1.0", {
status: 204 status: 204,
}); });
const { result, waitForNextUpdate } = renderHook(() => useDeleteTag(repository), { const { result, waitForNextUpdate } = renderHook(() => useDeleteTag(repository), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {

View File

@@ -28,9 +28,9 @@ const createInfiniteCachingClient = () => {
return new QueryClient({ return new QueryClient({
defaultOptions: { defaultOptions: {
queries: { queries: {
staleTime: Infinity staleTime: Infinity,
} },
} },
}); });
}; };

View File

@@ -22,22 +22,22 @@
* SOFTWARE. * SOFTWARE.
*/ */
import { QueryClient} from "react-query"; import { QueryClient } from "react-query";
export const setIndexLink = (queryClient: QueryClient, name: string, href: string) => { export const setIndexLink = (queryClient: QueryClient, name: string, href: string) => {
queryClient.setQueryData("index", { queryClient.setQueryData("index", {
version: "x.y.z", version: "x.y.z",
_links: { _links: {
[name]: { [name]: {
href: href href: href,
} },
} },
}); });
}; };
export const setEmptyIndex = (queryClient: QueryClient) => { export const setEmptyIndex = (queryClient: QueryClient) => {
queryClient.setQueryData("index", { queryClient.setQueryData("index", {
version: "x.y.z", version: "x.y.z",
_links: {} _links: {},
}); });
}; };

View File

@@ -22,12 +22,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
import { import { concat, getNamespaceAndPageFromMatch, getQueryStringFromLocation, withEndingSlash } from "./urls";
concat,
getNamespaceAndPageFromMatch,
getQueryStringFromLocation,
withEndingSlash
} from "./urls";
describe("tests for withEndingSlash", () => { describe("tests for withEndingSlash", () => {
it("should append missing slash", () => { it("should append missing slash", () => {
@@ -50,7 +45,7 @@ describe("concat tests", () => {
describe("tests for getNamespaceAndPageFromMatch", () => { describe("tests for getNamespaceAndPageFromMatch", () => {
function createMatch(namespace?: string, page?: string) { function createMatch(namespace?: string, page?: string) {
return { return {
params: { namespace, page } params: { namespace, page },
}; };
} }
@@ -88,7 +83,7 @@ describe("tests for getNamespaceAndPageFromMatch", () => {
describe("tests for getQueryStringFromLocation", () => { describe("tests for getQueryStringFromLocation", () => {
function createLocation(search: string) { function createLocation(search: string) {
return { return {
search search,
}; };
} }

View File

@@ -36,7 +36,7 @@ import {
useDeleteUser, useDeleteUser,
useUpdateUser, useUpdateUser,
useUser, useUser,
useUsers useUsers,
} from "./users"; } from "./users";
describe("Test user hooks", () => { describe("Test user hooks", () => {
@@ -48,21 +48,21 @@ describe("Test user hooks", () => {
name: "yoda", name: "yoda",
_links: { _links: {
delete: { delete: {
href: "/users/yoda" href: "/users/yoda",
}, },
update: { update: {
href: "/users/yoda" href: "/users/yoda",
}, },
convertToInternal: { convertToInternal: {
href: "/users/yoda/convertToInternal" href: "/users/yoda/convertToInternal",
}, },
convertToExternal: { convertToExternal: {
href: "/users/yoda/convertToExternal" href: "/users/yoda/convertToExternal",
} },
}, },
_embedded: { _embedded: {
members: [] members: [],
} },
}; };
const userCollection: UserCollection = { const userCollection: UserCollection = {
@@ -70,8 +70,8 @@ describe("Test user hooks", () => {
page: 0, page: 0,
pageTotal: 0, pageTotal: 0,
_embedded: { _embedded: {
users: [yoda] users: [yoda],
} },
}; };
afterEach(() => { afterEach(() => {
@@ -84,7 +84,7 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users"); setIndexLink(queryClient, "users", "/users");
fetchMock.get("/api/v2/users", userCollection); fetchMock.get("/api/v2/users", userCollection);
const { result, waitFor } = renderHook(() => useUsers(), { const { result, waitFor } = renderHook(() => useUsers(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(userCollection); expect(result.current.data).toEqual(userCollection);
@@ -95,11 +95,11 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users"); setIndexLink(queryClient, "users", "/users");
fetchMock.get("/api/v2/users", userCollection, { fetchMock.get("/api/v2/users", userCollection, {
query: { query: {
page: "42" page: "42",
} },
}); });
const { result, waitFor } = renderHook(() => useUsers({ page: 42 }), { const { result, waitFor } = renderHook(() => useUsers({ page: 42 }), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(userCollection); expect(result.current.data).toEqual(userCollection);
@@ -110,11 +110,11 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users"); setIndexLink(queryClient, "users", "/users");
fetchMock.get("/api/v2/users", userCollection, { fetchMock.get("/api/v2/users", userCollection, {
query: { query: {
q: "yoda" q: "yoda",
} },
}); });
const { result, waitFor } = renderHook(() => useUsers({ search: "yoda" }), { const { result, waitFor } = renderHook(() => useUsers({ search: "yoda" }), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(userCollection); expect(result.current.data).toEqual(userCollection);
@@ -125,7 +125,7 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users"); setIndexLink(queryClient, "users", "/users");
fetchMock.get("/api/v2/users", userCollection); fetchMock.get("/api/v2/users", userCollection);
const { result, waitFor } = renderHook(() => useUsers(), { const { result, waitFor } = renderHook(() => useUsers(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(queryClient.getQueryData(["user", "yoda"])).toEqual(yoda); expect(queryClient.getQueryData(["user", "yoda"])).toEqual(yoda);
@@ -138,7 +138,7 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users"); setIndexLink(queryClient, "users", "/users");
fetchMock.get("/api/v2/users/yoda", yoda); fetchMock.get("/api/v2/users/yoda", yoda);
const { result, waitFor } = renderHook(() => useUser("yoda"), { const { result, waitFor } = renderHook(() => useUser("yoda"), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await waitFor(() => !!result.current.data); await waitFor(() => !!result.current.data);
expect(result.current.data).toEqual(yoda); expect(result.current.data).toEqual(yoda);
@@ -153,14 +153,14 @@ describe("Test user hooks", () => {
fetchMock.postOnce("/api/v2/users", { fetchMock.postOnce("/api/v2/users", {
status: 201, status: 201,
headers: { headers: {
Location: "/users/yoda" Location: "/users/yoda",
} },
}); });
fetchMock.getOnce("/api/v2/users/yoda", yoda); fetchMock.getOnce("/api/v2/users/yoda", yoda);
const { result, waitForNextUpdate } = renderHook(() => useCreateUser(), { const { result, waitForNextUpdate } = renderHook(() => useCreateUser(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -177,13 +177,13 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users"); setIndexLink(queryClient, "users", "/users");
fetchMock.postOnce("/api/v2/users", { fetchMock.postOnce("/api/v2/users", {
status: 201 status: 201,
}); });
fetchMock.getOnce("/api/v2/users/yoda", yoda); fetchMock.getOnce("/api/v2/users/yoda", yoda);
const { result, waitForNextUpdate } = renderHook(() => useCreateUser(), { const { result, waitForNextUpdate } = renderHook(() => useCreateUser(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -202,11 +202,11 @@ describe("Test user hooks", () => {
setIndexLink(queryClient, "users", "/users"); setIndexLink(queryClient, "users", "/users");
fetchMock.deleteOnce("/api/v2/users/yoda", { fetchMock.deleteOnce("/api/v2/users/yoda", {
status: 200 status: 200,
}); });
const { result, waitForNextUpdate } = renderHook(() => useDeleteUser(), { const { result, waitForNextUpdate } = renderHook(() => useDeleteUser(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -229,17 +229,17 @@ describe("Test user hooks", () => {
const newJedis = { const newJedis = {
...yoda, ...yoda,
description: "may the 4th be with you" description: "may the 4th be with you",
}; };
fetchMock.putOnce("/api/v2/users/yoda", { fetchMock.putOnce("/api/v2/users/yoda", {
status: 200 status: 200,
}); });
fetchMock.getOnce("/api/v2/users/yoda", newJedis); fetchMock.getOnce("/api/v2/users/yoda", newJedis);
const { result, waitForNextUpdate } = renderHook(() => useUpdateUser(), { const { result, waitForNextUpdate } = renderHook(() => useUpdateUser(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -261,11 +261,11 @@ describe("Test user hooks", () => {
const queryClient = createInfiniteCachingClient(); const queryClient = createInfiniteCachingClient();
fetchMock.putOnce("/api/v2/users/yoda/convertToInternal", { fetchMock.putOnce("/api/v2/users/yoda/convertToInternal", {
status: 200 status: 200,
}); });
const { result, waitForNextUpdate } = renderHook(() => useConvertToInternal(), { const { result, waitForNextUpdate } = renderHook(() => useConvertToInternal(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {
@@ -287,11 +287,11 @@ describe("Test user hooks", () => {
const queryClient = createInfiniteCachingClient(); const queryClient = createInfiniteCachingClient();
fetchMock.putOnce("/api/v2/users/yoda/convertToExternal", { fetchMock.putOnce("/api/v2/users/yoda/convertToExternal", {
status: 200 status: 200,
}); });
const { result, waitForNextUpdate } = renderHook(() => useConvertToExternal(), { const { result, waitForNextUpdate } = renderHook(() => useConvertToExternal(), {
wrapper: createWrapper(undefined, queryClient) wrapper: createWrapper(undefined, queryClient),
}); });
await act(() => { await act(() => {

View File

@@ -24,6 +24,6 @@
export const createQueryString = (params: Record<string, string>) => { export const createQueryString = (params: Record<string, string>) => {
return Object.keys(params) return Object.keys(params)
.map(k => encodeURIComponent(k) + "=" + encodeURIComponent(params[k])) .map((k) => encodeURIComponent(k) + "=" + encodeURIComponent(params[k]))
.join("&"); .join("&");
}; };

View File

@@ -47,7 +47,7 @@ class Autocomplete extends React.Component<Props, State> {
static defaultProps = { static defaultProps = {
placeholder: "Type here", placeholder: "Type here",
loadingMessage: "Loading...", loadingMessage: "Loading...",
noOptionsMessage: "No suggestion available" noOptionsMessage: "No suggestion available",
}; };
handleInputChange = (newValue: ValueType<SelectValue>, action: ActionMeta) => { handleInputChange = (newValue: ValueType<SelectValue>, action: ActionMeta) => {
@@ -64,7 +64,7 @@ class Autocomplete extends React.Component<Props, State> {
selectValue: ValueType<SelectValue>, selectValue: ValueType<SelectValue>,
selectOptions: readonly SelectValue[] selectOptions: readonly SelectValue[]
): boolean => { ): boolean => {
const isNotDuplicated = !selectOptions.map(option => option.label).includes(inputValue); const isNotDuplicated = !selectOptions.map((option) => option.label).includes(inputValue);
const isNotEmpty = inputValue !== ""; const isNotEmpty = inputValue !== "";
return isNotEmpty && isNotDuplicated; return isNotEmpty && isNotDuplicated;
}; };
@@ -79,7 +79,7 @@ class Autocomplete extends React.Component<Props, State> {
noOptionsMessage, noOptionsMessage,
loadSuggestions, loadSuggestions,
creatable, creatable,
className className,
} = this.props; } = this.props;
return ( return (
<div className={classNames("field", className)}> <div className={classNames("field", className)}>
@@ -95,13 +95,13 @@ class Autocomplete extends React.Component<Props, State> {
loadingMessage={() => loadingMessage} loadingMessage={() => loadingMessage}
noOptionsMessage={() => noOptionsMessage} noOptionsMessage={() => noOptionsMessage}
isValidNewOption={this.isValidNewOption} isValidNewOption={this.isValidNewOption}
onCreateOption={value => { onCreateOption={(value) => {
this.selectValue({ this.selectValue({
label: value, label: value,
value: { value: {
id: value, id: value,
displayName: value displayName: value,
} },
}); });
}} }}
/> />

View File

@@ -41,5 +41,5 @@ const Wrapper = styled.div`
`; `;
storiesOf("BranchSelector", module) storiesOf("BranchSelector", module)
.addDecorator(storyFn => <Wrapper>{storyFn()}</Wrapper>) .addDecorator((storyFn) => <Wrapper>{storyFn()}</Wrapper>)
.add("Default", () => <BranchSelector branches={branches} onSelectBranch={branchSelected} label="Select Branch" />); .add("Default", () => <BranchSelector branches={branches} onSelectBranch={branchSelected} label="Select Branch" />);

View File

@@ -128,7 +128,10 @@ const Breadcrumb: FC<Props> = ({
if (path) { if (path) {
const paths = path.split("/"); const paths = path.split("/");
return paths.map((pathFragment, index) => { return paths.map((pathFragment, index) => {
let currPath = paths.slice(0, index + 1).map(encodeURIComponent).join("/"); let currPath = paths
.slice(0, index + 1)
.map(encodeURIComponent)
.join("/");
if (!currPath.endsWith("/")) { if (!currPath.endsWith("/")) {
currPath = currPath + "/"; currPath = currPath + "/";
} }

View File

@@ -43,8 +43,8 @@ const footerRight = <small>right footer</small>;
const baseDate = "2020-03-26T12:13:42+02:00"; const baseDate = "2020-03-26T12:13:42+02:00";
storiesOf("CardColumn", module) storiesOf("CardColumn", module)
.addDecorator(story => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>) .addDecorator((story) => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.addDecorator(storyFn => <Wrapper>{storyFn()}</Wrapper>) .addDecorator((storyFn) => <Wrapper>{storyFn()}</Wrapper>)
.add("Default", () => ( .add("Default", () => (
<CardColumn <CardColumn
link={link} link={link}

View File

@@ -69,13 +69,12 @@ const CardColumn: FC<Props> = ({
createLink = <Link className="overlay-column" to={link} />; createLink = <Link className="overlay-column" to={link} />;
} else if (action) { } else if (action) {
createLink = ( createLink = (
<a <button
className="overlay-column" className="overlay-column"
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
action(); action();
}} }}
href="#"
/> />
); );
} }

View File

@@ -28,6 +28,8 @@ type Props = {
className?: string; className?: string;
}; };
const HelpIcon: FC<Props> = ({ className }) => <Icon name="question-circle" color="blue-light" className={className} alt="" />; const HelpIcon: FC<Props> = ({ className }) => (
<Icon name="question-circle" color="blue-light" className={className} alt="" />
);
export default HelpIcon; export default HelpIcon;

View File

@@ -36,7 +36,7 @@ const colors = ["primary", "link", "info", "success", "warning", "danger", "whit
const sizing = ["xs", "sm", "lg", "2x", "3x", "5x", "7x", "10x"]; const sizing = ["xs", "sm", "lg", "2x", "3x", "5x", "7x", "10x"];
storiesOf("Icon", module) storiesOf("Icon", module)
.addDecorator(storyFn => <Wrapper>{storyFn()}</Wrapper>) .addDecorator((storyFn) => <Wrapper>{storyFn()}</Wrapper>)
.add("Default", () => ( .add("Default", () => (
<> <>
<Icon name="cat" /> <Icon name="cat" />
@@ -48,7 +48,7 @@ storiesOf("Icon", module)
.add("Colors", () => ( .add("Colors", () => (
<> <>
<Icon title="default color" name="cat" /> <Icon title="default color" name="cat" />
{colors.map(color => ( {colors.map((color) => (
<Icon key={color} title={color} name="cat" color={color} /> <Icon key={color} title={color} name="cat" color={color} />
))} ))}
</> </>
@@ -56,7 +56,7 @@ storiesOf("Icon", module)
.add("Sizing", () => ( .add("Sizing", () => (
<> <>
<Icon title="default size" name="cat" /> <Icon title="default size" name="cat" />
{sizing.map(size => ( {sizing.map((size) => (
<Icon key={size} title={"fa-" + size} name={"cat fa-" + size} /> <Icon key={size} title={"fa-" + size} name={"cat fa-" + size} />
))} ))}
</> </>

View File

@@ -44,7 +44,7 @@ const RoutingDecorator = (story: () => ReactNode) => <MemoryRouter initialEntrie
storiesOf("Notification", module) storiesOf("Notification", module)
.addDecorator(RoutingDecorator) .addDecorator(RoutingDecorator)
.addDecorator(storyFn => <Wrapper>{storyFn()}</Wrapper>) .addDecorator((storyFn) => <Wrapper>{storyFn()}</Wrapper>)
.add("Primary", () => <Notification type="primary">{content}</Notification>) .add("Primary", () => <Notification type="primary">{content}</Notification>)
.add("Success", () => <Notification type="success">{content}</Notification>) .add("Success", () => <Notification type="success">{content}</Notification>)
.add("Info", () => <Notification type="info">{content}</Notification>) .add("Info", () => <Notification type="info">{content}</Notification>)

View File

@@ -28,7 +28,7 @@ import Paginator from "./Paginator";
xdescribe("paginator rendering tests", () => { xdescribe("paginator rendering tests", () => {
const dummyLink = { const dummyLink = {
href: "https://dummy" href: "https://dummy",
}; };
it("should render all buttons but disabled, without links", () => { it("should render all buttons but disabled, without links", () => {
@@ -36,13 +36,13 @@ xdescribe("paginator rendering tests", () => {
page: 10, page: 10,
pageTotal: 20, pageTotal: 20,
_links: {}, _links: {},
_embedded: {} _embedded: {},
}; };
const paginator = shallow(<Paginator collection={collection} />); const paginator = shallow(<Paginator collection={collection} />);
const buttons = paginator.find("Button"); const buttons = paginator.find("Button");
expect(buttons.length).toBe(7); expect(buttons.length).toBe(7);
buttons.forEach(button => { buttons.forEach((button) => {
// @ts-ignore ??? // @ts-ignore ???
expect(button.props.disabled).toBeTruthy(); expect(button.props.disabled).toBeTruthy();
}); });
@@ -55,9 +55,9 @@ xdescribe("paginator rendering tests", () => {
_links: { _links: {
first: dummyLink, first: dummyLink,
next: dummyLink, next: dummyLink,
last: dummyLink last: dummyLink,
}, },
_embedded: {} _embedded: {},
}; };
const paginator = shallow(<Paginator collection={collection} />); const paginator = shallow(<Paginator collection={collection} />);
@@ -92,9 +92,9 @@ xdescribe("paginator rendering tests", () => {
first: dummyLink, first: dummyLink,
prev: dummyLink, prev: dummyLink,
next: dummyLink, next: dummyLink,
last: dummyLink last: dummyLink,
}, },
_embedded: {} _embedded: {},
}; };
const paginator = shallow(<Paginator collection={collection} />); const paginator = shallow(<Paginator collection={collection} />);
@@ -132,9 +132,9 @@ xdescribe("paginator rendering tests", () => {
pageTotal: 148, pageTotal: 148,
_links: { _links: {
first: dummyLink, first: dummyLink,
prev: dummyLink prev: dummyLink,
}, },
_embedded: {} _embedded: {},
}; };
const paginator = shallow(<Paginator collection={collection} />); const paginator = shallow(<Paginator collection={collection} />);
@@ -169,9 +169,9 @@ xdescribe("paginator rendering tests", () => {
first: dummyLink, first: dummyLink,
prev: dummyLink, prev: dummyLink,
next: dummyLink, next: dummyLink,
last: dummyLink last: dummyLink,
}, },
_embedded: {} _embedded: {},
}; };
const paginator = shallow(<Paginator collection={collection} />); const paginator = shallow(<Paginator collection={collection} />);
@@ -211,9 +211,9 @@ xdescribe("paginator rendering tests", () => {
first: dummyLink, first: dummyLink,
prev: dummyLink, prev: dummyLink,
next: dummyLink, next: dummyLink,
last: dummyLink last: dummyLink,
}, },
_embedded: {} _embedded: {},
}; };
const paginator = shallow(<Paginator collection={collection} />); const paginator = shallow(<Paginator collection={collection} />);
@@ -258,12 +258,12 @@ xdescribe("paginator rendering tests", () => {
_links: { _links: {
first: dummyLink, first: dummyLink,
prev: { prev: {
href: "https://www.scm-manager.org" href: "https://www.scm-manager.org",
}, },
next: dummyLink, next: dummyLink,
last: dummyLink last: dummyLink,
}, },
_embedded: {} _embedded: {},
}; };
let urlToOpen; let urlToOpen;

View File

@@ -33,7 +33,7 @@ class ProtectedRoute extends Component<Props> {
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
this.state = { this.state = {
error: undefined error: undefined,
}; };
} }
@@ -49,8 +49,8 @@ class ProtectedRoute extends Component<Props> {
to={{ to={{
pathname: "/login", pathname: "/login",
state: { state: {
from: routeProps.location from: routeProps.location,
} },
}} }}
/> />
); );

View File

@@ -64,7 +64,7 @@ const Tag: FC<Props> = ({
} }
let showDelete = null; let showDelete = null;
if (onRemove) { if (onRemove) {
showDelete = <a className="tag is-delete" onClick={onRemove} />; showDelete = <button className="tag is-delete" onClick={onRemove} />;
} }
return ( return (

View File

@@ -46,40 +46,40 @@ export default {
type: "normal", type: "normal",
oldLineNumber: 5, oldLineNumber: 5,
newLineNumber: 5, newLineNumber: 5,
isNormal: true isNormal: true,
}, },
{ {
content: "and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).", content: "and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).",
type: "normal", type: "normal",
oldLineNumber: 6, oldLineNumber: 6,
newLineNumber: 6, newLineNumber: 6,
isNormal: true isNormal: true,
}, },
{ {
content: "", content: "",
type: "normal", type: "normal",
oldLineNumber: 7, oldLineNumber: 7,
newLineNumber: 7, newLineNumber: 7,
isNormal: true isNormal: true,
}, },
{ {
content: "## Unreleased", content: "## Unreleased",
type: "delete", type: "delete",
lineNumber: 8, lineNumber: 8,
isDelete: true isDelete: true,
}, },
{ {
content: "## [2.7.1] - 2020-10-14", content: "## [2.7.1] - 2020-10-14",
type: "insert", type: "insert",
lineNumber: 8, lineNumber: 8,
isInsert: true isInsert: true,
}, },
{ {
content: "### Fixed", content: "### Fixed",
type: "normal", type: "normal",
oldLineNumber: 9, oldLineNumber: 9,
newLineNumber: 9, newLineNumber: 9,
isNormal: true isNormal: true,
}, },
{ {
content: content:
@@ -87,7 +87,7 @@ export default {
type: "normal", type: "normal",
oldLineNumber: 10, oldLineNumber: 10,
newLineNumber: 10, newLineNumber: 10,
isNormal: true isNormal: true,
}, },
{ {
content: content:
@@ -95,24 +95,22 @@ export default {
type: "normal", type: "normal",
oldLineNumber: 11, oldLineNumber: 11,
newLineNumber: 11, newLineNumber: 11,
isNormal: true isNormal: true,
} },
] ],
} },
], ],
_links: { _links: {
lines: { lines: {
href: href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/scm-manager/content/fbffdea2a566dc4ac54ea38d4aade5aaf541e7f2/CHANGELOG.md?start={start}&end={end}",
"http://localhost:8081/scm/api/v2/repositories/scmadmin/scm-manager/content/fbffdea2a566dc4ac54ea38d4aade5aaf541e7f2/CHANGELOG.md?start={start}&end={end}", templated: true,
templated: true },
} },
} },
}
], ],
_links: { _links: {
self: { self: {
href: href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/scm-manager/diff/fbffdea2a566dc4ac54ea38d4aade5aaf541e7f2/parsed",
"http://localhost:8081/scm/api/v2/repositories/scmadmin/scm-manager/diff/fbffdea2a566dc4ac54ea38d4aade5aaf541e7f2/parsed" },
} },
}
}; };

View File

@@ -22,7 +22,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
import {Changeset, ChangesetCollection, PagedCollection} from "@scm-manager/ui-types"; import { Changeset, ChangesetCollection, PagedCollection } from "@scm-manager/ui-types";
const one: Changeset = { const one: Changeset = {
id: "a88567ef1e9528a700555cad8c4576b72fc7c6dd", id: "a88567ef1e9528a700555cad8c4576b72fc7c6dd",
@@ -33,31 +33,26 @@ const one: Changeset = {
contributors: [ contributors: [
{ {
type: "Committed-by", type: "Committed-by",
person: { mail: "zaphod.beeblebrox@hitchhiker.cm", name: "Zaphod Beeblebrox" } person: { mail: "zaphod.beeblebrox@hitchhiker.cm", name: "Zaphod Beeblebrox" },
}, },
{ type: "Co-authored-by", person: { mail: "ford.prefect@hitchhiker.com", name: "Ford Prefect" } } { type: "Co-authored-by", person: { mail: "ford.prefect@hitchhiker.com", name: "Ford Prefect" } },
], ],
_links: { _links: {
self: { self: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/a88567ef1e9528a700555cad8c4576b72fc7c6dd"
}, },
diff: { diff: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd"
}, },
sources: { sources: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/a88567ef1e9528a700555cad8c4576b72fc7c6dd"
}, },
modifications: { modifications: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/a88567ef1e9528a700555cad8c4576b72fc7c6dd"
}, },
diffParsed: { diffParsed: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd/parsed",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd/parsed" },
}
}, },
_embedded: { _embedded: {
tags: [], tags: [],
@@ -67,17 +62,15 @@ const one: Changeset = {
id: "d21cc6c359270aef2196796f4d96af65f51866dc", id: "d21cc6c359270aef2196796f4d96af65f51866dc",
_links: { _links: {
self: { self: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc"
}, },
diff: { diff: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc" },
} },
} },
} ],
] },
}
}; };
const two: Changeset = { const two: Changeset = {
@@ -88,30 +81,25 @@ const two: Changeset = {
contributors: [ contributors: [
{ {
type: "Committed-by", type: "Committed-by",
person: { mail: "zaphod.beeblebrox@hitchhiker.cm", name: "Zaphod Beeblebrox" } person: { mail: "zaphod.beeblebrox@hitchhiker.cm", name: "Zaphod Beeblebrox" },
} },
], ],
_links: { _links: {
self: { self: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc"
}, },
diff: { diff: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc"
}, },
sources: { sources: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/d21cc6c359270aef2196796f4d96af65f51866dc",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/d21cc6c359270aef2196796f4d96af65f51866dc"
}, },
modifications: { modifications: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/d21cc6c359270aef2196796f4d96af65f51866dc",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/d21cc6c359270aef2196796f4d96af65f51866dc"
}, },
diffParsed: { diffParsed: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc/parsed",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc/parsed" },
}
}, },
_embedded: { _embedded: {
tags: [], tags: [],
@@ -121,17 +109,15 @@ const two: Changeset = {
id: "e163c8f632db571c9aa51a8eb440e37cf550b825", id: "e163c8f632db571c9aa51a8eb440e37cf550b825",
_links: { _links: {
self: { self: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825"
}, },
diff: { diff: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825" },
} },
} },
} ],
] },
}
}; };
const three: Changeset = { const three: Changeset = {
@@ -142,27 +128,22 @@ const three: Changeset = {
contributors: [], contributors: [],
_links: { _links: {
self: { self: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825"
}, },
diff: { diff: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825"
}, },
sources: { sources: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/e163c8f632db571c9aa51a8eb440e37cf550b825",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/e163c8f632db571c9aa51a8eb440e37cf550b825"
}, },
modifications: { modifications: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/e163c8f632db571c9aa51a8eb440e37cf550b825",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/e163c8f632db571c9aa51a8eb440e37cf550b825"
}, },
diffParsed: { diffParsed: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825/parsed",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825/parsed" },
}
}, },
_embedded: { tags: [], branches: [], parents: [] } _embedded: { tags: [], branches: [], parents: [] },
}; };
const four: Changeset = { const four: Changeset = {
@@ -173,29 +154,24 @@ const four: Changeset = {
contributors: [ contributors: [
{ type: "Co-authored-by", person: { mail: "ford.prefect@hitchhiker.com", name: "Ford Prefect" } }, { type: "Co-authored-by", person: { mail: "ford.prefect@hitchhiker.com", name: "Ford Prefect" } },
{ type: "Co-authored-by", person: { mail: "zaphod.beeblebrox@hitchhiker.cm", name: "Zaphod Beeblebrox" } }, { type: "Co-authored-by", person: { mail: "zaphod.beeblebrox@hitchhiker.cm", name: "Zaphod Beeblebrox" } },
{ type: "Co-authored-by", person: { mail: "trillian@hitchhiker.cm", name: "Tricia Marie McMillan" } } { type: "Co-authored-by", person: { mail: "trillian@hitchhiker.cm", name: "Tricia Marie McMillan" } },
], ],
_links: { _links: {
self: { self: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930"
}, },
diff: { diff: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930"
}, },
sources: { sources: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930"
}, },
modifications: { modifications: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930"
}, },
diffParsed: { diffParsed: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930/parsed",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/b6c6f8fbd0d490936fae7d26ffdd4695cc2a0930/parsed" },
}
}, },
_embedded: { _embedded: {
tags: [], tags: [],
@@ -205,17 +181,15 @@ const four: Changeset = {
id: "a88567ef1e9528a700555cad8c4576b72fc7c6dd", id: "a88567ef1e9528a700555cad8c4576b72fc7c6dd",
_links: { _links: {
self: { self: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/a88567ef1e9528a700555cad8c4576b72fc7c6dd"
}, },
diff: { diff: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/a88567ef1e9528a700555cad8c4576b72fc7c6dd" },
} },
} },
} ],
] },
}
}; };
const five: Changeset = { const five: Changeset = {
@@ -225,25 +199,20 @@ const five: Changeset = {
description: "HOG-42 Change mail to arthur@guide.galaxy\n\n", description: "HOG-42 Change mail to arthur@guide.galaxy\n\n",
_links: { _links: {
self: { self: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/d21cc6c359270aef2196796f4d96af65f51866dc"
}, },
diff: { diff: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc"
}, },
sources: { sources: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/d21cc6c359270aef2196796f4d96af65f51866dc",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/sources/d21cc6c359270aef2196796f4d96af65f51866dc"
}, },
modifications: { modifications: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/d21cc6c359270aef2196796f4d96af65f51866dc",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/modifications/d21cc6c359270aef2196796f4d96af65f51866dc"
}, },
diffParsed: { diffParsed: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc/parsed",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/d21cc6c359270aef2196796f4d96af65f51866dc/parsed" },
}
}, },
_embedded: { _embedded: {
tags: [], tags: [],
@@ -253,17 +222,15 @@ const five: Changeset = {
id: "e163c8f632db571c9aa51a8eb440e37cf550b825", id: "e163c8f632db571c9aa51a8eb440e37cf550b825",
_links: { _links: {
self: { self: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/changesets/e163c8f632db571c9aa51a8eb440e37cf550b825"
}, },
diff: { diff: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/diff/e163c8f632db571c9aa51a8eb440e37cf550b825" },
} },
} },
} ],
] },
}
}; };
const changesets: ChangesetCollection = { const changesets: ChangesetCollection = {
@@ -271,27 +238,24 @@ const changesets: ChangesetCollection = {
pageTotal: 1, pageTotal: 1,
_links: { _links: {
self: { self: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10"
}, },
first: { first: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10"
}, },
last: { last: {
href: href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10",
"http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master/changesets/?page=0&pageSize=10" },
}
}, },
_embedded: { _embedded: {
changesets: [one, two, three, four], changesets: [one, two, three, four],
branch: { branch: {
name: "master", name: "master",
_links: { _links: {
self: { href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master" } self: { href: "http://localhost:8081/scm/api/v2/repositories/hitchhiker/heart-of-gold/branches/master" },
} },
} },
} },
}; };
export { one, two, three, four, five }; export { one, two, three, four, five };

View File

@@ -37,31 +37,31 @@ export default {
permissions: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/permissions/" }, permissions: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/permissions/" },
protocol: [ protocol: [
{ href: "ssh://scmadmin@localhost:4567/repo/scmadmin/Git", name: "ssh" }, { href: "ssh://scmadmin@localhost:4567/repo/scmadmin/Git", name: "ssh" },
{ href: "http://localhost:8081/scm/repo/scmadmin/Git", name: "http" } { href: "http://localhost:8081/scm/repo/scmadmin/Git", name: "http" },
], ],
tags: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/tags/" }, tags: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/tags/" },
branches: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/branches/" }, branches: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/branches/" },
incomingChangesets: { incomingChangesets: {
href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/changesets", href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/changesets",
templated: true templated: true,
}, },
incomingDiff: { incomingDiff: {
href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/diff", href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/diff",
templated: true templated: true,
}, },
incomingDiffParsed: { incomingDiffParsed: {
href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/diff/parsed", href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/diff/parsed",
templated: true templated: true,
}, },
changesets: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/changesets/" }, changesets: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/changesets/" },
sources: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/sources/" }, sources: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/sources/" },
authorMappingConfig: { authorMappingConfig: {
href: "http://localhost:8081/scm/api/v2/authormapping/configuration/scmadmin/Git" href: "http://localhost:8081/scm/api/v2/authormapping/configuration/scmadmin/Git",
}, },
unfavorize: { href: "http://localhost:8081/scm/api/v2/unfavorize/scmadmin/Git" }, unfavorize: { href: "http://localhost:8081/scm/api/v2/unfavorize/scmadmin/Git" },
favorites: [ favorites: [
{ href: "http://localhost:8081/scm/api/v2/unfavorize/scmadmin/Git", name: "unfavorize" }, { href: "http://localhost:8081/scm/api/v2/unfavorize/scmadmin/Git", name: "unfavorize" },
{ href: "http://localhost:8081/scm/api/v2/favorize/scmadmin/Git", name: "favorize" } { href: "http://localhost:8081/scm/api/v2/favorize/scmadmin/Git", name: "favorize" },
] ],
} },
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -21,9 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
import React, { MouseEvent, ReactNode } from "react"; import React, { FC, MouseEvent, ReactNode } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { RouteComponentProps, withRouter } from "react-router-dom"; import { Link } from "react-router-dom";
import Icon from "../Icon"; import Icon from "../Icon";
import { createAttributesForTesting } from "../devBuild"; import { createAttributesForTesting } from "../devBuild";
@@ -42,90 +42,79 @@ export type ButtonProps = {
testId?: string; testId?: string;
}; };
type Props = ButtonProps & type Props = ButtonProps & {
RouteComponentProps & { type?: "button" | "submit" | "reset";
type?: "button" | "submit" | "reset"; color?: string;
color?: string; };
const Button: FC<Props> = ({
link,
className,
icon,
fullWidth,
reducedMobile,
testId,
children,
label,
type = "button",
title,
loading,
disabled,
action,
color = "default",
}) => {
const renderIcon = () => {
return <>{icon ? <Icon name={icon} color="inherit" className="is-medium pr-1" /> : null}</>;
}; };
class Button extends React.Component<Props> { if (link) {
static defaultProps: Partial<Props> = {
type: "button",
color: "default",
};
onClick = (event: React.MouseEvent) => {
const { action, link, history } = this.props;
if (action) {
action(event);
} else if (link) {
history.push(link);
}
};
render() {
const {
label,
title,
loading,
disabled,
type,
color,
className,
icon,
fullWidth,
reducedMobile,
children,
testId,
} = this.props;
if (icon) {
return (
<button
type={type}
title={title}
disabled={disabled}
onClick={this.onClick}
className={classNames(
"button",
"is-" + color,
{ "is-loading": loading },
{ "is-fullwidth": fullWidth },
{ "is-reduced-mobile": reducedMobile },
className
)}
{...createAttributesForTesting(testId)}
>
<span className="icon is-medium">
<Icon name={icon} color="inherit" />
</span>
{(label || children) && (
<span>
{label} {children}
</span>
)}
</button>
);
}
return ( return (
<button <Link
type={type}
title={title}
disabled={disabled}
onClick={this.onClick}
className={classNames( className={classNames(
"button", "button",
"is-" + color, "is-" + color,
{ "is-loading": loading }, { "is-loading": loading },
{ "is-fullwidth": fullWidth }, { "is-fullwidth": fullWidth },
{ "is-reduced-mobile": reducedMobile },
className className
)} )}
{...createAttributesForTesting(testId)} to={link}
aria-label={label}
> >
{label} {children} {renderIcon()}{" "}
</button> {(label || children) && (
<>
{label} {children}
</>
)}
</Link>
); );
} }
}
export default withRouter(Button); return (
<button
type={type}
title={title}
disabled={disabled}
onClick={(event) => action && action(event)}
className={classNames(
"button",
"is-" + color,
{ "is-loading": loading },
{ "is-fullwidth": fullWidth },
{ "is-reduced-mobile": reducedMobile },
className
)}
{...createAttributesForTesting(testId)}
>
{renderIcon()}{" "}
{(label || children) && (
<>
{label} {children}
</>
)}
</button>
);
};
export default Button;

View File

@@ -41,7 +41,7 @@ class ButtonAddons extends React.Component<Props> {
const { className, children } = this.props; const { className, children } = this.props;
const childWrapper: ReactNode[] = []; const childWrapper: ReactNode[] = [];
React.Children.forEach(children, child => { React.Children.forEach(children, (child) => {
if (child) { if (child) {
childWrapper.push( childWrapper.push(
<p className="control" key={childWrapper.length}> <p className="control" key={childWrapper.length}>

View File

@@ -34,7 +34,7 @@ class ButtonGroup extends React.Component<Props> {
const { className, children } = this.props; const { className, children } = this.props;
const childWrapper: ReactNode[] = []; const childWrapper: ReactNode[] = [];
React.Children.forEach(children, child => { React.Children.forEach(children, (child) => {
if (child) { if (child) {
childWrapper.push( childWrapper.push(
<div className="control" key={childWrapper.length}> <div className="control" key={childWrapper.length}>

View File

@@ -31,7 +31,7 @@ type SubmitButtonProps = ButtonProps & {
class SubmitButton extends React.Component<SubmitButtonProps> { class SubmitButton extends React.Component<SubmitButtonProps> {
static defaultProps = { static defaultProps = {
scrollToTop: true scrollToTop: true,
}; };
render() { render() {

View File

@@ -46,7 +46,7 @@ storiesOf("Buttons/Button", module)
.addDecorator(RoutingDecorator) .addDecorator(RoutingDecorator)
.add("Colors", () => ( .add("Colors", () => (
<div> <div>
{colors.map(color => ( {colors.map((color) => (
<Spacing key={color}> <Spacing key={color}>
<Button color={color} label={color} /> <Button color={color} label={color} />
</Spacing> </Spacing>
@@ -62,7 +62,7 @@ storiesOf("Buttons/Button", module)
)) ))
.add("Disabled", () => ( .add("Disabled", () => (
<div> <div>
{colors.map(color => ( {colors.map((color) => (
<Spacing key={color}> <Spacing key={color}>
<Button color={color} label={color} disabled={true} /> <Button color={color} label={color} disabled={true} />
</Spacing> </Spacing>

View File

@@ -26,12 +26,12 @@ import { byKey, byValueLength, byNestedKeys } from "./comparators";
const createObject = (key: string, value?: string) => { const createObject = (key: string, value?: string) => {
return { return {
[key]: value [key]: value,
}; };
}; };
const createObjects = (key: string, values: Array<string | undefined>) => { const createObjects = (key: string, values: Array<string | undefined>) => {
return values.map(v => createObject(key, v)); return values.map((v) => createObject(key, v));
}; };
describe("key comparator tests", () => { describe("key comparator tests", () => {
@@ -98,18 +98,18 @@ describe("nested key comparator tests", () => {
const createObject = (key: string, nested?: string, value?: string) => { const createObject = (key: string, nested?: string, value?: string) => {
if (!nested) { if (!nested) {
return { return {
[key]: undefined [key]: undefined,
}; };
} }
return { return {
[key]: { [key]: {
[nested]: value [nested]: value,
} },
}; };
}; };
const createObjects = (key: string, nested: string, values: Array<string | undefined>) => { const createObjects = (key: string, nested: string, values: Array<string | undefined>) => {
return values.map(v => createObject(key, nested, v)); return values.map((v) => createObject(key, nested, v));
}; };
it("should sort array", () => { it("should sort array", () => {

View File

@@ -95,5 +95,5 @@ export const byNestedKeys = (key: string, nestedKey: string) => {
export default { export default {
byKey, byKey,
byValueLength, byValueLength,
byNestedKeys byNestedKeys,
}; };

View File

@@ -31,7 +31,7 @@ export const createAttributesForTesting = (testId?: string) => {
return undefined; return undefined;
} }
return { return {
"data-testid": normalizeTestId(testId) "data-testid": normalizeTestId(testId),
}; };
}; };

View File

@@ -53,7 +53,7 @@ const AutocompleteAddEntryToTableField: FC<Props> = ({
loadSuggestions, loadSuggestions,
placeholder, placeholder,
loadingMessage, loadingMessage,
noOptionsMessage noOptionsMessage,
}) => { }) => {
const [selectedValue, setSelectedValue] = useState<SelectValue | undefined>(undefined); const [selectedValue, setSelectedValue] = useState<SelectValue | undefined>(undefined);

View File

@@ -64,8 +64,8 @@ const ReactHookForm: FC = () => {
const { register, handleSubmit } = useForm<Settings>({ const { register, handleSubmit } = useForm<Settings>({
defaultValues: { defaultValues: {
disabled: true, disabled: true,
readonly: true readonly: true,
} },
}); });
const [stored, setStored] = useState<Settings>(); const [stored, setStored] = useState<Settings>();
@@ -106,7 +106,7 @@ const LegacyEvents: FC = () => {
}; };
storiesOf("Forms/Checkbox", module) storiesOf("Forms/Checkbox", module)
.addDecorator(storyFn => <MemoryRouter>{storyFn()}</MemoryRouter>) .addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
.add("Default", () => ( .add("Default", () => (
<Spacing> <Spacing>
<Checkbox label="Not checked" checked={false} /> <Checkbox label="Not checked" checked={false} />

View File

@@ -41,10 +41,10 @@ storiesOf("Forms/DropDown", module)
options={[ options={[
"The Hitchhiker's Guide to the Galaxy", "The Hitchhiker's Guide to the Galaxy",
"Dirk Gentlys Holistic Detective Agency", "Dirk Gentlys Holistic Detective Agency",
"The Meaning Of Liff" "The Meaning Of Liff",
]} ]}
preselectedOption={"dirk"} preselectedOption={"dirk"}
optionSelected={selection => { optionSelected={(selection) => {
// nothing to do // nothing to do
}} }}
/> />
@@ -54,7 +54,7 @@ storiesOf("Forms/DropDown", module)
optionValues={["alpha", "beta", "gamma"]} optionValues={["alpha", "beta", "gamma"]}
options={["A", "B", "C"]} options={["A", "B", "C"]}
preselectedOption={"D"} preselectedOption={"D"}
optionSelected={selection => { optionSelected={(selection) => {
// nothing to do // nothing to do
}} }}
/> />

View File

@@ -45,7 +45,7 @@ class DropDown extends React.Component<Props> {
render() { render() {
const { options, optionValues, preselectedOption, className, disabled } = this.props; const { options, optionValues, preselectedOption, className, disabled } = this.props;
if (preselectedOption && options.filter(o => o === preselectedOption).length === 0) { if (preselectedOption && options.filter((o) => o === preselectedOption).length === 0) {
options.push(preselectedOption); options.push(preselectedOption);
} }

View File

@@ -77,7 +77,7 @@ const FilterInput: FC<Props> = ({ filter, value, testId, placeholder, autoFocus,
type="search" type="search"
placeholder={placeholder || t("filterEntries")} placeholder={placeholder || t("filterEntries")}
value={stateValue} value={stateValue}
onChange={event => setStateValue(event.target.value)} onChange={(event) => setStateValue(event.target.value)}
autoFocus={autoFocus || false} autoFocus={autoFocus || false}
/> />
<span className="icon is-small is-left"> <span className="icon is-small is-left">

View File

@@ -36,11 +36,11 @@ type Props = WithTranslation & {
class MemberNameTagGroup extends React.Component<Props> { class MemberNameTagGroup extends React.Component<Props> {
render() { render() {
const { members, label, helpText, t } = this.props; const { members, label, helpText, t } = this.props;
const membersExtended = members.map(id => { const membersExtended = members.map((id) => {
return { return {
id, id,
displayName: id, displayName: id,
mail: "" mail: "",
}; };
}); });
return ( return (
@@ -54,7 +54,7 @@ class MemberNameTagGroup extends React.Component<Props> {
} }
removeEntry = (membersExtended: DisplayedUser[]) => { removeEntry = (membersExtended: DisplayedUser[]) => {
const members = membersExtended.map(function(item) { const members = membersExtended.map(function (item) {
return item["id"]; return item["id"];
}); });
this.props.memberListChanged(members); this.props.memberListChanged(members);

View File

@@ -44,7 +44,7 @@ class PasswordConfirmation extends React.Component<Props, State> {
password: "", password: "",
confirmedPassword: "", confirmedPassword: "",
passwordValid: true, passwordValid: true,
passwordConfirmationFailed: false passwordConfirmationFailed: false,
}; };
} }
@@ -53,7 +53,7 @@ class PasswordConfirmation extends React.Component<Props, State> {
password: "", password: "",
confirmedPassword: "", confirmedPassword: "",
passwordValid: true, passwordValid: true,
passwordConfirmationFailed: false passwordConfirmationFailed: false,
}); });
} }
@@ -101,7 +101,7 @@ class PasswordConfirmation extends React.Component<Props, State> {
this.setState( this.setState(
{ {
confirmedPassword, confirmedPassword,
passwordConfirmationFailed: !passwordConfirmed passwordConfirmationFailed: !passwordConfirmed,
}, },
this.propagateChange this.propagateChange
); );
@@ -114,7 +114,7 @@ class PasswordConfirmation extends React.Component<Props, State> {
{ {
passwordValid: this.validatePassword(password), passwordValid: this.validatePassword(password),
passwordConfirmationFailed, passwordConfirmationFailed,
password: password password: password,
}, },
this.propagateChange this.propagateChange
); );

View File

@@ -113,7 +113,7 @@ const LegacyEvents: FC = () => {
}; };
storiesOf("Forms/Radio", module) storiesOf("Forms/Radio", module)
.addDecorator(storyFn => <MemoryRouter>{storyFn()}</MemoryRouter>) .addDecorator((storyFn) => <MemoryRouter>{storyFn()}</MemoryRouter>)
.add("Default", () => ( .add("Default", () => (
<Spacing> <Spacing>
<Radio label="Not checked" checked={false} /> <Radio label="Not checked" checked={false} />

View File

@@ -187,8 +187,8 @@ const PreselectOption: FC = () => {
}, },
{ {
label: "USCSS Prometheus", label: "USCSS Prometheus",
value: "uscss-prometheus" value: "uscss-prometheus",
} },
]} ]}
onChange={setValue} onChange={setValue}
value={value} value={value}
@@ -204,5 +204,4 @@ storiesOf("Forms/Select", module)
.add("Ref", () => <Ref />) .add("Ref", () => <Ref />)
.add("Legacy Events", () => <LegacyEvents />) .add("Legacy Events", () => <LegacyEvents />)
.add("ReactHookForm", () => <ReactHookForm />) .add("ReactHookForm", () => <ReactHookForm />)
.add("Preselect option", () => <PreselectOption />) .add("Preselect option", () => <PreselectOption />);
;

View File

@@ -24,7 +24,7 @@
// this aliases are only to map from spotter detection to prismjs // this aliases are only to map from spotter detection to prismjs
const languageAliases: { [key: string]: string } = { const languageAliases: { [key: string]: string } = {
golang: "go" golang: "go",
}; };
export const defaultLanguage = "text"; export const defaultLanguage = "text";

View File

@@ -40,7 +40,7 @@ const trillian: Me = {
displayName: "Trillian McMillian", displayName: "Trillian McMillian",
mail: "tricia@hitchhiker.com", mail: "tricia@hitchhiker.com",
groups: ["crew"], groups: ["crew"],
_links: {} _links: {},
}; };
const bindAvatar = (binder: Binder, avatar: string) => { const bindAvatar = (binder: Binder, avatar: string) => {
@@ -65,7 +65,7 @@ const withBinder = (binder: Binder) => {
}; };
storiesOf("Footer", module) storiesOf("Footer", module)
.addDecorator(story => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>) .addDecorator((story) => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.add("Default", () => { .add("Default", () => {
return <Footer me={trillian} version="2.0.0" links={{}} />; return <Footer me={trillian} version="2.0.0" links={{}} />;
}) })

View File

@@ -29,7 +29,7 @@ const SecondaryColumn = styled.div<{ collapsed: boolean }>`
/* In Bulma there is unfortunately no intermediate step between .is-1 and .is-2, hence the size. /* In Bulma there is unfortunately no intermediate step between .is-1 and .is-2, hence the size.
Navigation size should be as constant as possible. */ Navigation size should be as constant as possible. */
flex: none; flex: none;
width: ${props => (props.collapsed ? "5.5rem" : "20.5rem")}; width: ${(props) => (props.collapsed ? "5.5rem" : "20.5rem")};
max-width: ${(props: { collapsed: boolean }) => (props.collapsed ? "11.3%" : "25%")}; max-width: ${(props: { collapsed: boolean }) => (props.collapsed ? "11.3%" : "25%")};
/* Render this column to full size if column construct breaks (page size too small). */ /* Render this column to full size if column construct breaks (page size too small). */
@media (max-width: 785px) { @media (max-width: 785px) {

View File

@@ -31,7 +31,7 @@ type Props = {
className?: string; className?: string;
}; };
const Title: FC<Props> = ({ title, preventRefreshingPageTitle, customPageTitle, className , children}) => { const Title: FC<Props> = ({ title, preventRefreshingPageTitle, customPageTitle, className, children }) => {
useEffect(() => { useEffect(() => {
if (!preventRefreshingPageTitle) { if (!preventRefreshingPageTitle) {
if (customPageTitle) { if (customPageTitle) {
@@ -51,7 +51,7 @@ const Title: FC<Props> = ({ title, preventRefreshingPageTitle, customPageTitle,
}; };
Title.defaultProps = { Title.defaultProps = {
preventRefreshingPageTitle: false preventRefreshingPageTitle: false,
}; };
export default Title; export default Title;

View File

@@ -32,7 +32,7 @@ type Props = {
value: string; value: string;
}; };
const MarkdownCodeRenderer: FC<Props> = props => { const MarkdownCodeRenderer: FC<Props> = (props) => {
const binder = useBinder(); const binder = useBinder();
const indexLinks = useIndexLinks(); const indexLinks = useIndexLinks();
const { language } = props; const { language } = props;

View File

@@ -94,7 +94,7 @@ const MarkdownHeadingRenderer: FC<Props> = ({ children, level, permalink, id })
<Icon name="link" onClick={copyPermalink} alt={t("sources.content.copyPermalink")} /> <Icon name="link" onClick={copyPermalink} alt={t("sources.content.copyPermalink")} />
</Tooltip> </Tooltip>
); );
const headingElement = React.createElement("h" + level, {id: anchorId}, [...reactChildren, CopyButton]); const headingElement = React.createElement("h" + level, { id: anchorId }, [...reactChildren, CopyButton]);
const href = urls.withContextPath(location.pathname + "#" + anchorId); const href = urls.withContextPath(location.pathname + "#" + anchorId);
const permalinkHref = const permalinkHref =
window.location.protocol + window.location.protocol +
@@ -110,7 +110,7 @@ const MarkdownHeadingRenderer: FC<Props> = ({ children, level, permalink, id })
}; };
export const create = (permalink: string): FC<Props> => { export const create = (permalink: string): FC<Props> => {
return props => <MarkdownHeadingRenderer {...props} permalink={permalink} />; return (props) => <MarkdownHeadingRenderer {...props} permalink={permalink} />;
}; };
export default MarkdownHeadingRenderer; export default MarkdownHeadingRenderer;

View File

@@ -26,7 +26,7 @@ import {
isExternalLink, isExternalLink,
isLinkWithProtocol, isLinkWithProtocol,
createLocalLink, createLocalLink,
isInternalScmRepoLink isInternalScmRepoLink,
} from "./MarkdownLinkRenderer"; } from "./MarkdownLinkRenderer";
describe("test isAnchorLink", () => { describe("test isAnchorLink", () => {

View File

@@ -136,7 +136,7 @@ const MarkdownLinkRenderer: FC<Props> = ({ href = "", base, children, ...props }
// we use a factory method, because react-markdown does not pass // we use a factory method, because react-markdown does not pass
// base as prop down to our link component. // base as prop down to our link component.
export const create = (base?: string, protocolExtensions: ProtocolLinkRendererExtensionMap = {}): FC<LinkProps> => { export const create = (base?: string, protocolExtensions: ProtocolLinkRendererExtensionMap = {}): FC<LinkProps> => {
return props => { return (props) => {
const protocolLinkContext = isLinkWithProtocol(props.href || ""); const protocolLinkContext = isLinkWithProtocol(props.href || "");
if (protocolLinkContext) { if (protocolLinkContext) {
const { link, protocol } = protocolLinkContext; const { link, protocol } = protocolLinkContext;

View File

@@ -46,8 +46,8 @@ const Spacing = styled.div`
`; `;
storiesOf("MarkdownView", module) storiesOf("MarkdownView", module)
.addDecorator(story => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>) .addDecorator((story) => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.addDecorator(story => <Spacing>{story()}</Spacing>) .addDecorator((story) => <Spacing>{story()}</Spacing>)
.add("Default", () => <MarkdownView content={TestPage} skipHtml={false} />) .add("Default", () => <MarkdownView content={TestPage} skipHtml={false} />)
.add("Skip Html", () => <MarkdownView content={TestPage} skipHtml={true} />) .add("Skip Html", () => <MarkdownView content={TestPage} skipHtml={true} />)
.add("Code without Lang", () => <MarkdownView content={MarkdownWithoutLang} skipHtml={false} />) .add("Code without Lang", () => <MarkdownView content={MarkdownWithoutLang} skipHtml={false} />)
@@ -63,7 +63,7 @@ storiesOf("MarkdownView", module)
const binder = new Binder("custom protocol link renderer"); const binder = new Binder("custom protocol link renderer");
binder.bind("markdown-renderer.link.protocol", { binder.bind("markdown-renderer.link.protocol", {
protocol: "scw", protocol: "scw",
renderer: ProtocolLinkRenderer renderer: ProtocolLinkRenderer,
} as ProtocolLinkRendererExtension); } as ProtocolLinkRendererExtension);
return ( return (
<BinderContext.Provider value={binder}> <BinderContext.Provider value={binder}>
@@ -75,7 +75,7 @@ storiesOf("MarkdownView", module)
const binder = new Binder("custom protocol link renderer"); const binder = new Binder("custom protocol link renderer");
binder.bind("markdown-renderer.link.protocol", { binder.bind("markdown-renderer.link.protocol", {
protocol: "scw", protocol: "scw",
renderer: ProtocolLinkRenderer renderer: ProtocolLinkRenderer,
} as ProtocolLinkRendererExtension); } as ProtocolLinkRendererExtension);
return ( return (
<BinderContext.Provider value={binder}> <BinderContext.Provider value={binder}>

View File

@@ -85,7 +85,7 @@ const MarkdownErrorNotification: FC = () => {
</pre> </pre>
<p> <p>
{t("markdownErrorNotification.spec")}:{" "} {t("markdownErrorNotification.spec")}:{" "}
<a href="https://github.github.com/gfm/" target="_blank"> <a href="https://github.github.com/gfm/" target="_blank" rel="noreferrer">
GitHub Flavored Markdown Spec GitHub Flavored Markdown Spec
</a> </a>
</p> </p>
@@ -99,13 +99,13 @@ class MarkdownView extends React.Component<Props, State> {
static defaultProps: Partial<Props> = { static defaultProps: Partial<Props> = {
enableAnchorHeadings: false, enableAnchorHeadings: false,
skipHtml: false skipHtml: false,
}; };
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
this.state = { this.state = {
contentRef: null contentRef: null,
}; };
} }
@@ -143,7 +143,7 @@ class MarkdownView extends React.Component<Props, State> {
basePath, basePath,
permalink, permalink,
t, t,
mdastPlugins = [] mdastPlugins = [],
} = this.props; } = this.props;
const rendererFactory = this.context.getExtension("markdown-renderer-factory"); const rendererFactory = this.context.getExtension("markdown-renderer-factory");
@@ -200,25 +200,25 @@ class MarkdownView extends React.Component<Props, State> {
sanitize, sanitize,
merge(gh, { merge(gh, {
attributes: { attributes: {
code: ["className"] // Allow className for code elements, this is necessary to extract the code language code: ["className"], // Allow className for code elements, this is necessary to extract the code language
}, },
clobberPrefix: "", // Do not prefix user-provided ids and class names, clobberPrefix: "", // Do not prefix user-provided ids and class names,
protocols: { protocols: {
href: Object.keys(protocolLinkRendererExtensions) href: Object.keys(protocolLinkRendererExtensions),
} },
}) })
) )
.use(rehype2react, { .use(rehype2react, {
createElement: React.createElement, createElement: React.createElement,
passNode: true, passNode: true,
components: createComponentList(remarkRendererList, { permalink }) components: createComponentList(remarkRendererList, { permalink }),
}); });
const renderedMarkdown: any = processor.processSync(content).result; const renderedMarkdown: any = processor.processSync(content).result;
return ( return (
<ErrorBoundary fallback={MarkdownErrorNotification}> <ErrorBoundary fallback={MarkdownErrorNotification}>
<div ref={el => this.setState({ contentRef: el })} className="content is-word-break"> <div ref={(el) => this.setState({ contentRef: el })} className="content is-word-break">
{renderedMarkdown} {renderedMarkdown}
</div> </div>
</ErrorBoundary> </ErrorBoundary>

View File

@@ -24,7 +24,7 @@
import { import {
createRemark2RehypeCodeRendererAdapter, createRemark2RehypeCodeRendererAdapter,
createRemark2RehypeHeadingRendererAdapterFactory, createRemark2RehypeHeadingRendererAdapterFactory,
createRemark2RehypeLinkRendererAdapter createRemark2RehypeLinkRendererAdapter,
} from "./remarkToRehypeRendererAdapters"; } from "./remarkToRehypeRendererAdapters";
export type CreateComponentListOptions = { export type CreateComponentListOptions = {

View File

@@ -34,7 +34,7 @@ export default function createMdastPlugin(plugin: AstPlugin): any {
return function attach() { return function attach() {
return function transform(tree: any) { return function transform(tree: any) {
plugin({ plugin({
visit: (type, visitor) => visit(tree, type, visitor) visit: (type, visitor) => visit(tree, type, visitor),
}); });
return tree; return tree;
}; };

View File

@@ -35,4 +35,4 @@ export type ProtocolLinkRendererExtension = {
export type ProtocolLinkRendererExtensionMap = { export type ProtocolLinkRendererExtensionMap = {
[protocol: string]: FC<ProtocolLinkRendererProps>; [protocol: string]: FC<ProtocolLinkRendererProps>;
} };

View File

@@ -59,7 +59,7 @@ export const createTransformer = (t: TFunction): AstPlugin => {
if (i > 0) { if (i > 0) {
children.push({ children.push({
type: "text", type: "text",
value: nodeText.substring(0, i) value: nodeText.substring(0, i),
}); });
} }
@@ -69,14 +69,14 @@ export const createTransformer = (t: TFunction): AstPlugin => {
title: t("changeset.shortlink.title", { title: t("changeset.shortlink.title", {
namespace: m[1], namespace: m[1],
name: m[2], name: m[2],
id: m[3] id: m[3],
}), }),
children: [ children: [
{ {
type: "text", type: "text",
value: m[0] value: m[0],
} },
] ],
}); });
nodeText = nodeText.substring(i + m[0].length); nodeText = nodeText.substring(i + m[0].length);
@@ -85,13 +85,13 @@ export const createTransformer = (t: TFunction): AstPlugin => {
if (nodeText.length > 0) { if (nodeText.length > 0) {
children.push({ children.push({
type: "text", type: "text",
value: nodeText value: nodeText,
}); });
} }
parent.children[index] = { parent.children[index] = {
type: "text", type: "text",
children children,
}; };
} }
}); });

View File

@@ -28,7 +28,7 @@ export const createRemark2RehypeCodeRendererAdapter = (remarkRenderer: any) => {
children = children || []; children = children || [];
const renderProps = { const renderProps = {
value: children[0], value: children[0],
language: Array.isArray(node.properties.className) ? node.properties.className[0].split("language-")[1] : "" language: Array.isArray(node.properties.className) ? node.properties.className[0].split("language-")[1] : "",
}; };
return React.createElement(remarkRenderer, renderProps, ...children); return React.createElement(remarkRenderer, renderProps, ...children);
}; };
@@ -54,13 +54,14 @@ export const createRemark2RehypeLinkRendererAdapter = (remarkRenderer: any) => {
}; };
export const createRemark2RehypeHeadingRendererAdapterFactory = (remarkRenderer: any, permalink?: string) => { export const createRemark2RehypeHeadingRendererAdapterFactory = (remarkRenderer: any, permalink?: string) => {
return (level: number) => ({ node, children }: any) => { return (level: number) =>
const renderProps = { ({ node, children }: any) => {
id: node.properties.id, const renderProps = {
level, id: node.properties.id,
permalink level,
permalink,
};
children = children || [];
return React.createElement(remarkRenderer, renderProps, ...children);
}; };
children = children || [];
return React.createElement(remarkRenderer, renderProps, ...children);
};
}; };

View File

@@ -37,15 +37,15 @@ const buttons = [
{ {
className: "is-outlined", className: "is-outlined",
label: "Cancel", label: "Cancel",
onClick: () => null onClick: () => null,
}, },
{ {
label: "Submit" label: "Submit",
} },
]; ];
storiesOf("Modal/ConfirmAlert", module) storiesOf("Modal/ConfirmAlert", module)
.addDecorator(story => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>) .addDecorator((story) => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
.add("Default", () => <ConfirmAlert message={body} title={"Are you sure about that?"} buttons={buttons} />) .add("Default", () => <ConfirmAlert message={body} title={"Are you sure about that?"} buttons={buttons} />)
.add("WithButton", () => { .add("WithButton", () => {
const buttonClick = () => { const buttonClick = () => {

View File

@@ -65,13 +65,13 @@ export const ConfirmAlert: FC<Props> = ({ title, message, buttons, close }) => {
<div className="field is-grouped"> <div className="field is-grouped">
{buttons.map((button, index) => ( {buttons.map((button, index) => (
<p className="control" key={index}> <p className="control" key={index}>
<a <button
className={classNames("button", "is-info", button.className, button.isLoading ? "is-loading" : "")} className={classNames("button", "is-info", button.className, button.isLoading ? "is-loading" : "")}
key={index} key={index}
onClick={() => handleClickButton(button)} onClick={() => handleClickButton(button)}
> >
{button.label} {button.label}
</a> </button>
</p> </p>
))} ))}
</div> </div>

View File

@@ -48,8 +48,8 @@ const CreateTagModal: FC<Props> = ({ t, onClose, tagCreationLink, existingTagsLi
useEffect(() => { useEffect(() => {
apiClient apiClient
.get(existingTagsLink) .get(existingTagsLink)
.then(response => response.json()) .then((response) => response.json())
.then(json => setTagNames(json._embedded.tags.map((tag: Tag) => tag.name))); .then((json) => setTagNames(json._embedded.tags.map((tag: Tag) => tag.name)));
}, [existingTagsLink]); }, [existingTagsLink]);
const createTag = () => { const createTag = () => {
@@ -57,7 +57,7 @@ const CreateTagModal: FC<Props> = ({ t, onClose, tagCreationLink, existingTagsLi
apiClient apiClient
.post(tagCreationLink, { .post(tagCreationLink, {
revision, revision,
name: newTagName name: newTagName,
}) })
.then(onCreated) .then(onCreated)
.catch(onError) .catch(onError)
@@ -83,7 +83,7 @@ const CreateTagModal: FC<Props> = ({ t, onClose, tagCreationLink, existingTagsLi
<InputField <InputField
name="name" name="name"
label={t("tags.create.form.field.name.label")} label={t("tags.create.form.field.name.label")}
onChange={val => setNewTagName(val)} onChange={(val) => setNewTagName(val)}
value={newTagName} value={newTagName}
validationError={!!validationError} validationError={!!validationError}
errorMessage={t(validationError)} errorMessage={t(validationError)}

View File

@@ -33,7 +33,7 @@ export const MenuContext = React.createContext<MenuContext>({
isCollapsed() { isCollapsed() {
return false; return false;
}, },
setCollapsed() {} setCollapsed() {},
}); });
export const StateMenuContextProvider: FC = ({ children }) => { export const StateMenuContextProvider: FC = ({ children }) => {
@@ -43,7 +43,7 @@ export const StateMenuContextProvider: FC = ({ children }) => {
isCollapsed() { isCollapsed() {
return collapsed; return collapsed;
}, },
setCollapsed setCollapsed,
}; };
return <MenuContext.Provider value={context}>{children}</MenuContext.Provider>; return <MenuContext.Provider value={context}>{children}</MenuContext.Provider>;

View File

@@ -39,17 +39,17 @@ class NavAction extends React.Component<Props> {
if (icon) { if (icon) {
showIcon = ( showIcon = (
<> <>
<i className={icon}></i>{" "} <i className={icon} />{" "}
</> </>
); );
} }
return ( return (
<li> <li>
<a onClick={action} href="javascript:void(0);"> <button onClick={action}>
{showIcon} {showIcon}
{label} {label}
</a> </button>
</li> </li>
); );
} }

View File

@@ -53,8 +53,8 @@ const withRoute = (route: string) => {
}; };
storiesOf("Secondary Navigation", module) storiesOf("Secondary Navigation", module)
.addDecorator(story => <StateMenuContextProvider>{story()}</StateMenuContextProvider>) .addDecorator((story) => <StateMenuContextProvider>{story()}</StateMenuContextProvider>)
.addDecorator(story => ( .addDecorator((story) => (
<Columns className="columns"> <Columns className="columns">
<div className="column is-3">{story()}</div> <div className="column is-3">{story()}</div>
</Columns> </Columns>
@@ -92,7 +92,7 @@ storiesOf("Secondary Navigation", module)
<SecondaryNavigation label="Hitchhiker"> <SecondaryNavigation label="Hitchhiker">
<SecondaryNavigationItem to="/42" icon="fas fa-puzzle-piece" label="Puzzle 42" title="Puzzle 42" /> <SecondaryNavigationItem to="/42" icon="fas fa-puzzle-piece" label="Puzzle 42" title="Puzzle 42" />
<SecondaryNavigationItem <SecondaryNavigationItem
activeWhenMatch={route => route.location.pathname === "/hog"} activeWhenMatch={(route) => route.location.pathname === "/hog"}
to="/heart-of-gold" to="/heart-of-gold"
icon="fas fa-star" icon="fas fa-star"
label="Heart Of Gold" label="Heart Of Gold"

View File

@@ -44,7 +44,7 @@ const SubNavigation: FC<Props> = ({
title, title,
label, label,
children, children,
testId testId,
}) => { }) => {
const context = useMenuContext(); const context = useMenuContext();
const collapsed = context.isCollapsed(); const collapsed = context.isCollapsed();
@@ -56,7 +56,7 @@ const SubNavigation: FC<Props> = ({
const active = useActiveMatch({ const active = useActiveMatch({
to: parent, to: parent,
activeOnlyWhenExact, activeOnlyWhenExact,
activeWhenMatch activeWhenMatch,
}); });
let defaultIcon = "fas fa-cog"; let defaultIcon = "fas fa-cog";

View File

@@ -34,40 +34,42 @@ const Wrapper = styled.div`
`; `;
storiesOf("Popover", module) storiesOf("Popover", module)
.addDecorator(storyFn => <Wrapper>{storyFn()}</Wrapper>) .addDecorator((storyFn) => <Wrapper>{storyFn()}</Wrapper>)
.add("Default", () => React.createElement(() => { .add("Default", () =>
const { triggerProps, popoverProps } = usePopover(); React.createElement(() => {
const { triggerProps, popoverProps } = usePopover();
return ( return (
<div> <div>
<Popover title={<strong>Spaceship Heart of Gold</strong>} width={512} {...popoverProps}> <Popover title={<strong>Spaceship Heart of Gold</strong>} width={512} {...popoverProps}>
<p> <p>
The Heart of Gold is the sleekest, most advanced, coolest spaceship in the galaxy. Its stunning good looks The Heart of Gold is the sleekest, most advanced, coolest spaceship in the galaxy. Its stunning good looks
mirror its awesome speed and power. It is powered by the revolutionary new Infinite Improbability Drive, mirror its awesome speed and power. It is powered by the revolutionary new Infinite Improbability Drive,
which lets the ship pass through every point in every universe simultaneously. which lets the ship pass through every point in every universe simultaneously.
</p> </p>
</Popover> </Popover>
<button className="button" {...triggerProps}> <button className="button" {...triggerProps}>
Trigger Trigger
</button> </button>
</div> </div>
); );
})) })
.add("Link", () => React.createElement(() => { )
const { triggerProps, popoverProps } = usePopover(); .add("Link", () =>
React.createElement(() => {
const { triggerProps, popoverProps } = usePopover();
return ( return (
<div> <div>
<Popover title={<strong>Spaceship Heart of Gold</strong>} width={512} {...popoverProps}> <Popover title={<strong>Spaceship Heart of Gold</strong>} width={512} {...popoverProps}>
<p> <p>
The Heart of Gold is the sleekest, most advanced, coolest spaceship in the galaxy. Its stunning good looks The Heart of Gold is the sleekest, most advanced, coolest spaceship in the galaxy. Its stunning good looks
mirror its awesome speed and power. It is powered by the revolutionary new Infinite Improbability Drive, mirror its awesome speed and power. It is powered by the revolutionary new Infinite Improbability Drive,
which lets the ship pass through every point in every universe simultaneously. which lets the ship pass through every point in every universe simultaneously.
</p> </p>
</Popover> </Popover>
<a href="#" {...triggerProps}> <button {...triggerProps}>Trigger</button>
Trigger </div>
</a> );
</div> })
); );
}));

View File

@@ -53,7 +53,7 @@ type State = {
const initialState = { const initialState = {
onPopover: false, onPopover: false,
onTrigger: false onTrigger: false,
}; };
const reducer = (state: State, action: Action): State => { const reducer = (state: State, action: Action): State => {
@@ -66,14 +66,14 @@ const reducer = (state: State, action: Action): State => {
offsetTop: action.offsetTop, offsetTop: action.offsetTop,
offsetLeft: action.offsetLeft, offsetLeft: action.offsetLeft,
onTrigger: true, onTrigger: true,
onPopover: false onPopover: false,
}; };
} }
case "leave-trigger": { case "leave-trigger": {
if (state.onPopover) { if (state.onPopover) {
return { return {
...state, ...state,
onTrigger: false onTrigger: false,
}; };
} }
return initialState; return initialState;
@@ -81,14 +81,14 @@ const reducer = (state: State, action: Action): State => {
case "enter-popover": { case "enter-popover": {
return { return {
...state, ...state,
onPopover: true onPopover: true,
}; };
} }
case "leave-popover": { case "leave-popover": {
if (state.onTrigger) { if (state.onTrigger) {
return { return {
...state, ...state,
onPopover: false onPopover: false,
}; };
} }
return initialState; return initialState;
@@ -109,13 +109,13 @@ const usePopover = () => {
dispatchDeferred(dispatch, { dispatchDeferred(dispatch, {
type: "enter-trigger", type: "enter-trigger",
offsetTop: current.offsetTop, offsetTop: current.offsetTop,
offsetLeft: current.offsetLeft + current.offsetWidth / 2 offsetLeft: current.offsetLeft + current.offsetWidth / 2,
}); });
}; };
const onMouseLeave = () => { const onMouseLeave = () => {
dispatchDeferred(dispatch, { dispatchDeferred(dispatch, {
type: "leave-trigger" type: "leave-trigger",
}); });
}; };
@@ -123,14 +123,14 @@ const usePopover = () => {
triggerProps: { triggerProps: {
onMouseOver, onMouseOver,
onMouseLeave, onMouseLeave,
ref: (node: HTMLElement | null) => (triggerRef.current = node) ref: (node: HTMLElement | null) => (triggerRef.current = node),
}, },
popoverProps: { popoverProps: {
dispatch, dispatch,
show: state.onPopover || state.onTrigger, show: state.onPopover || state.onTrigger,
offsetTop: state.offsetTop, offsetTop: state.offsetTop,
offsetLeft: state.offsetLeft offsetLeft: state.offsetLeft,
} },
}; };
}; };

View File

@@ -42,8 +42,8 @@ const HUNK_0: Hunk = {
{ content: "line", type: "insert", lineNumber: 5, isInsert: true }, { content: "line", type: "insert", lineNumber: 5, isInsert: true },
{ content: "line", type: "normal", oldLineNumber: 6, newLineNumber: 6, isNormal: true }, { content: "line", type: "normal", oldLineNumber: 6, newLineNumber: 6, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 7, newLineNumber: 7, isNormal: true }, { content: "line", type: "normal", oldLineNumber: 7, newLineNumber: 7, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 8, newLineNumber: 8, isNormal: true } { content: "line", type: "normal", oldLineNumber: 8, newLineNumber: 8, isNormal: true },
] ],
}; };
const HUNK_1: Hunk = { const HUNK_1: Hunk = {
content: "@@ -14,6 +14,7 @@", content: "@@ -14,6 +14,7 @@",
@@ -58,8 +58,8 @@ const HUNK_1: Hunk = {
{ content: "line", type: "insert", lineNumber: 17, isInsert: true }, { content: "line", type: "insert", lineNumber: 17, isInsert: true },
{ content: "line", type: "normal", oldLineNumber: 17, newLineNumber: 18, isNormal: true }, { content: "line", type: "normal", oldLineNumber: 17, newLineNumber: 18, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 18, newLineNumber: 19, isNormal: true }, { content: "line", type: "normal", oldLineNumber: 18, newLineNumber: 19, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 19, newLineNumber: 20, isNormal: true } { content: "line", type: "normal", oldLineNumber: 19, newLineNumber: 20, isNormal: true },
] ],
}; };
const HUNK_2: Hunk = { const HUNK_2: Hunk = {
content: "@@ -21,7 +22,7 @@", content: "@@ -21,7 +22,7 @@",
@@ -75,8 +75,8 @@ const HUNK_2: Hunk = {
{ content: "line", type: "insert", lineNumber: 25, isInsert: true }, { content: "line", type: "insert", lineNumber: 25, isInsert: true },
{ content: "line", type: "normal", oldLineNumber: 25, newLineNumber: 26, isNormal: true }, { content: "line", type: "normal", oldLineNumber: 25, newLineNumber: 26, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 26, newLineNumber: 27, isNormal: true }, { content: "line", type: "normal", oldLineNumber: 26, newLineNumber: 27, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 27, newLineNumber: 28, isNormal: true } { content: "line", type: "normal", oldLineNumber: 27, newLineNumber: 28, isNormal: true },
] ],
}; };
const HUNK_3: Hunk = { const HUNK_3: Hunk = {
content: "@@ -33,6 +34,7 @@", content: "@@ -33,6 +34,7 @@",
@@ -91,8 +91,8 @@ const HUNK_3: Hunk = {
{ content: "line", type: "insert", lineNumber: 37, isInsert: true }, { content: "line", type: "insert", lineNumber: 37, isInsert: true },
{ content: "line", type: "normal", oldLineNumber: 36, newLineNumber: 38, isNormal: true }, { content: "line", type: "normal", oldLineNumber: 36, newLineNumber: 38, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 37, newLineNumber: 39, isNormal: true }, { content: "line", type: "normal", oldLineNumber: 37, newLineNumber: 39, isNormal: true },
{ content: "line", type: "normal", oldLineNumber: 38, newLineNumber: 40, isNormal: true } { content: "line", type: "normal", oldLineNumber: 38, newLineNumber: 40, isNormal: true },
] ],
}; };
const TEST_CONTENT_WITH_HUNKS: FileDiff = { const TEST_CONTENT_WITH_HUNKS: FileDiff = {
hunks: [HUNK_0, HUNK_1, HUNK_2, HUNK_3], hunks: [HUNK_0, HUNK_1, HUNK_2, HUNK_3],
@@ -107,9 +107,9 @@ const TEST_CONTENT_WITH_HUNKS: FileDiff = {
_links: { _links: {
lines: { lines: {
href: "http://localhost:8081/scm/api/v2/content/abc/CommitMessage.js?start={start}&end={end}", href: "http://localhost:8081/scm/api/v2/content/abc/CommitMessage.js?start={start}&end={end}",
templated: true templated: true,
} },
} },
}; };
const TEST_CONTENT_WITH_NEW_BINARY_FILE: FileDiff = { const TEST_CONTENT_WITH_NEW_BINARY_FILE: FileDiff = {
@@ -119,7 +119,7 @@ const TEST_CONTENT_WITH_NEW_BINARY_FILE: FileDiff = {
newEndingNewLine: true, newEndingNewLine: true,
oldRevision: "0000000000000000000000000000000000000000", oldRevision: "0000000000000000000000000000000000000000",
newRevision: "86c370aae0727d628a5438f79a5cdd45752b9d99", newRevision: "86c370aae0727d628a5438f79a5cdd45752b9d99",
type: "add" type: "add",
}; };
const TEST_CONTENT_WITH_NEW_TEXT_FILE: FileDiff = { const TEST_CONTENT_WITH_NEW_TEXT_FILE: FileDiff = {
@@ -138,17 +138,16 @@ const TEST_CONTENT_WITH_NEW_TEXT_FILE: FileDiff = {
newLines: 2, newLines: 2,
changes: [ changes: [
{ content: "line 1", type: "insert", lineNumber: 1, isInsert: true }, { content: "line 1", type: "insert", lineNumber: 1, isInsert: true },
{ content: "line 2", type: "insert", lineNumber: 2, isInsert: true } { content: "line 2", type: "insert", lineNumber: 2, isInsert: true },
] ],
} },
], ],
_links: { _links: {
lines: { lines: {
href: href: "http://localhost:8081/scm/api/v2/repositories/scm-manager/scm-editor-plugin/content/c63898d35520ee47bcc3a8291660979918715762/src/main/markdown/README.md?start={start}&end={end}",
"http://localhost:8081/scm/api/v2/repositories/scm-manager/scm-editor-plugin/content/c63898d35520ee47bcc3a8291660979918715762/src/main/markdown/README.md?start={start}&end={end}", templated: true,
templated: true },
} },
}
}; };
const TEST_CONTENT_WITH_DELETED_TEXT_FILE: FileDiff = { const TEST_CONTENT_WITH_DELETED_TEXT_FILE: FileDiff = {
@@ -165,10 +164,10 @@ const TEST_CONTENT_WITH_DELETED_TEXT_FILE: FileDiff = {
content: "@@ -1 +0,0 @@", content: "@@ -1 +0,0 @@",
oldStart: 1, oldStart: 1,
oldLines: 1, oldLines: 1,
changes: [{ content: "# scm-editor-plugin", type: "delete", lineNumber: 1, isDelete: true }] changes: [{ content: "# scm-editor-plugin", type: "delete", lineNumber: 1, isDelete: true }],
} },
], ],
_links: { lines: { href: "http://localhost:8081/dev/null?start={start}&end={end}", templated: true } } _links: { lines: { href: "http://localhost:8081/dev/null?start={start}&end={end}", templated: true } },
}; };
const TEST_CONTENT_WITH_DELETED_LINES_AT_END: FileDiff = { const TEST_CONTENT_WITH_DELETED_LINES_AT_END: FileDiff = {
@@ -202,16 +201,16 @@ const TEST_CONTENT_WITH_DELETED_LINES_AT_END: FileDiff = {
{ content: "line", type: "delete", lineNumber: 119, isDelete: true }, { content: "line", type: "delete", lineNumber: 119, isDelete: true },
{ content: "line", type: "delete", lineNumber: 120, isDelete: true }, { content: "line", type: "delete", lineNumber: 120, isDelete: true },
{ content: "line", type: "delete", lineNumber: 121, isDelete: true }, { content: "line", type: "delete", lineNumber: 121, isDelete: true },
{ content: "line", type: "delete", lineNumber: 122, isDelete: true } { content: "line", type: "delete", lineNumber: 122, isDelete: true },
] ],
} },
], ],
_links: { _links: {
lines: { lines: {
href: "http://localhost:8081/scm/api/v2/content/abc/CommitMessage.js?start={start}&end={end}", href: "http://localhost:8081/scm/api/v2/content/abc/CommitMessage.js?start={start}&end={end}",
templated: true templated: true,
} },
} },
}; };
const TEST_CONTENT_WITH_ALL_LINES_REMOVED_FROM_FILE: FileDiff = { const TEST_CONTENT_WITH_ALL_LINES_REMOVED_FROM_FILE: FileDiff = {
@@ -231,17 +230,16 @@ const TEST_CONTENT_WITH_ALL_LINES_REMOVED_FROM_FILE: FileDiff = {
changes: [ changes: [
{ content: "line", type: "delete", lineNumber: 1, isDelete: true }, { content: "line", type: "delete", lineNumber: 1, isDelete: true },
{ content: "line", type: "delete", lineNumber: 2, isDelete: true }, { content: "line", type: "delete", lineNumber: 2, isDelete: true },
{ content: "line", type: "delete", lineNumber: 3, isDelete: true } { content: "line", type: "delete", lineNumber: 3, isDelete: true },
] ],
} },
], ],
_links: { _links: {
lines: { lines: {
href: href: "http://localhost:8081/scm/api/v2/repositories/scm-manager/scm-editor-plugin/content/b313a7690f028c77df98417c1ed6cba67e5692ec/pom.xml?start={start}&end={end}",
"http://localhost:8081/scm/api/v2/repositories/scm-manager/scm-editor-plugin/content/b313a7690f028c77df98417c1ed6cba67e5692ec/pom.xml?start={start}&end={end}", templated: true,
templated: true },
} },
}
}; };
describe("with hunks the diff expander", () => { describe("with hunks the diff expander", () => {
@@ -285,7 +283,7 @@ describe("with hunks the diff expander", () => {
await diffExpander await diffExpander
.getHunk(1) .getHunk(1)
.expandBottom(1) .expandBottom(1)
.then(file => (newFile = file)); .then((file) => (newFile = file));
expect(fetchMock.done()).toBe(true); expect(fetchMock.done()).toBe(true);
expect(newFile!.hunks!.length).toBe(oldHunkCount + 1); expect(newFile!.hunks!.length).toBe(oldHunkCount + 1);
expect(newFile!.hunks![1]).toBe(expandedHunk); expect(newFile!.hunks![1]).toBe(expandedHunk);
@@ -310,7 +308,7 @@ describe("with hunks the diff expander", () => {
await diffExpander await diffExpander
.getHunk(1) .getHunk(1)
.expandHead(5) .expandHead(5)
.then(file => (newFile = file)); .then((file) => (newFile = file));
expect(fetchMock.done()).toBe(true); expect(fetchMock.done()).toBe(true);
expect(newFile!.hunks!.length).toBe(oldHunkCount + 1); expect(newFile!.hunks!.length).toBe(oldHunkCount + 1);
expect(newFile!.hunks![0]).toBe(preceedingHunk); expect(newFile!.hunks![0]).toBe(preceedingHunk);
@@ -339,7 +337,7 @@ describe("with hunks the diff expander", () => {
await diffExpander await diffExpander
.getHunk(3) .getHunk(3)
.expandBottom(10) .expandBottom(10)
.then(file => (newFile = file)); .then((file) => (newFile = file));
expect(newFile!.hunks!.length).toBe(oldHunkCount + 1); expect(newFile!.hunks!.length).toBe(oldHunkCount + 1);
expect(newFile!.hunks![4].fullyExpanded).toBe(true); expect(newFile!.hunks![4].fullyExpanded).toBe(true);
}); });
@@ -352,7 +350,7 @@ describe("with hunks the diff expander", () => {
await diffExpander await diffExpander
.getHunk(3) .getHunk(3)
.expandBottom(-1) .expandBottom(-1)
.then(file => (newFile = file)); .then((file) => (newFile = file));
await fetchMock.flush(true); await fetchMock.flush(true);
expect(newFile!.hunks![4].fullyExpanded).toBe(true); expect(newFile!.hunks![4].fullyExpanded).toBe(true);
}); });

View File

@@ -75,7 +75,7 @@ class DiffExpander {
expandHead: (n: number, count: number) => Promise<FileDiff> = (n, count) => { expandHead: (n: number, count: number) => Promise<FileDiff> = (n, count) => {
const start = this.minLineNumber(n) - Math.min(count, this.computeMaxExpandHeadRange(n)) - 1; const start = this.minLineNumber(n) - Math.min(count, this.computeMaxExpandHeadRange(n)) - 1;
const end = this.minLineNumber(n) - 1; const end = this.minLineNumber(n) - 1;
return this.loadLines(start, end).then(lines => { return this.loadLines(start, end).then((lines) => {
const hunk = this.file.hunks![n]; const hunk = this.file.hunks![n];
const newHunk = this.createNewHunk( const newHunk = this.createNewHunk(
@@ -96,7 +96,7 @@ class DiffExpander {
count > 0 count > 0
? start + Math.min(count, maxExpandBottomRange > 0 ? maxExpandBottomRange : Number.MAX_SAFE_INTEGER) ? start + Math.min(count, maxExpandBottomRange > 0 ? maxExpandBottomRange : Number.MAX_SAFE_INTEGER)
: -1; : -1;
return this.loadLines(start, end).then(lines => { return this.loadLines(start, end).then((lines) => {
const hunk = this.file.hunks![n]; const hunk = this.file.hunks![n];
const newHunk: Hunk = this.createNewHunk( const newHunk: Hunk = this.createNewHunk(
@@ -116,9 +116,9 @@ class DiffExpander {
.replace("{end}", end.toString()); .replace("{end}", end.toString());
return apiClient return apiClient
.get(lineRequestUrl) .get(lineRequestUrl)
.then(response => response.text()) .then((response) => response.text())
.then(text => text.split("\n")) .then((text) => text.split("\n"))
.then(lines => (lines[lines.length - 1] === "" ? lines.slice(0, lines.length - 1) : lines)); .then((lines) => (lines[lines.length - 1] === "" ? lines.slice(0, lines.length - 1) : lines));
}; };
addHunkToFile = (newHunk: Hunk, position: number) => { addHunkToFile = (newHunk: Hunk, position: number) => {
@@ -141,13 +141,13 @@ class DiffExpander {
let oldLineNumber: number = oldFirstLineNumber; let oldLineNumber: number = oldFirstLineNumber;
let newLineNumber: number = newFirstLineNumber; let newLineNumber: number = newFirstLineNumber;
lines.forEach(line => { lines.forEach((line) => {
newChanges.push({ newChanges.push({
content: line, content: line,
type: "normal", type: "normal",
oldLineNumber, oldLineNumber,
newLineNumber, newLineNumber,
isNormal: true isNormal: true,
}); });
oldLineNumber += 1; oldLineNumber += 1;
newLineNumber += 1; newLineNumber += 1;
@@ -161,7 +161,7 @@ class DiffExpander {
oldLines: lines.length, oldLines: lines.length,
newLines: lines.length, newLines: lines.length,
expansion: true, expansion: true,
fullyExpanded: requestedLines < 0 || lines.length < requestedLines fullyExpanded: requestedLines < 0 || lines.length < requestedLines,
}; };
}; };
@@ -175,13 +175,13 @@ class DiffExpander {
return lastChange.newLineNumber || lastChange.lineNumber!; return lastChange.newLineNumber || lastChange.lineNumber!;
}; };
getHunk: (n: number) => ExpandableHunk = n => { getHunk: (n: number) => ExpandableHunk = (n) => {
return { return {
maxExpandHeadRange: this.computeMaxExpandHeadRange(n), maxExpandHeadRange: this.computeMaxExpandHeadRange(n),
maxExpandBottomRange: this.computeMaxExpandBottomRange(n), maxExpandBottomRange: this.computeMaxExpandBottomRange(n),
expandHead: (count: number) => this.expandHead(n, count), expandHead: (count: number) => this.expandHead(n, count),
expandBottom: (count: number) => this.expandBottom(n, count), expandBottom: (count: number) => this.expandBottom(n, count),
hunk: this.file?.hunks![n] hunk: this.file?.hunks![n],
}; };
}; };
} }

View File

@@ -24,7 +24,7 @@
import React, { FC } from "react"; import React, { FC } from "react";
import { Color, Size } from "../styleConstants"; import { Color, Size } from "../styleConstants";
import Tooltip, {TooltipLocation} from "../Tooltip"; import Tooltip, { TooltipLocation } from "../Tooltip";
import Tag from "../Tag"; import Tag from "../Tag";
type Props = { type Props = {

View File

@@ -49,7 +49,7 @@ function runTokenize({ id, payload }: TokenizeMessage) {
const options = { const options = {
highlight: language !== "text", highlight: language !== "text",
language: language, language: language,
refractor refractor,
}; };
const doTokenization = (worker: Worker) => { const doTokenization = (worker: Worker) => {
@@ -57,13 +57,13 @@ function runTokenize({ id, payload }: TokenizeMessage) {
const tokens = tokenize(hunks, options); const tokens = tokenize(hunks, options);
const payload = { const payload = {
success: true, success: true,
tokens: tokens tokens: tokens,
}; };
worker.postMessage({ id, payload }); worker.postMessage({ id, payload });
} catch (ex) { } catch (ex) {
const payload = { const payload = {
success: false, success: false,
reason: ex.message reason: ex.message,
}; };
worker.postMessage({ id, payload }); worker.postMessage({ id, payload });
} }

View File

@@ -73,7 +73,7 @@ type Props = {
const TokenizedDiffView: FC<Props> = ({ file, viewType, className, children }) => { const TokenizedDiffView: FC<Props> = ({ file, viewType, className, children }) => {
const { tokens } = useTokenizeWorker(tokenize, { const { tokens } = useTokenizeWorker(tokenize, {
hunks: file.hunks, hunks: file.hunks,
language: determineLanguage(file.language) language: determineLanguage(file.language),
}); });
return ( return (

View File

@@ -40,30 +40,30 @@ const commitCreateNewApp = {
revision: "0d8c1d328f4599b363755671afe667c7ace52bae", revision: "0d8c1d328f4599b363755671afe667c7ace52bae",
author: { author: {
name: "Arthur Dent", name: "Arthur Dent",
mail: "arthur.dent@hitchhiker.com" mail: "arthur.dent@hitchhiker.com",
}, },
description: "create new app", description: "create new app",
when: new Date("2020-04-09T13:07:42Z") when: new Date("2020-04-09T13:07:42Z"),
}; };
const commitFixedMissingImport = { const commitFixedMissingImport = {
revision: "fab38559ce3ab8c388e067712b4bd7ab94b9fa9b", revision: "fab38559ce3ab8c388e067712b4bd7ab94b9fa9b",
author: { author: {
name: "Tricia Marie McMillan", name: "Tricia Marie McMillan",
mail: "trillian@hitchhiker.com" mail: "trillian@hitchhiker.com",
}, },
description: "fixed missing import", description: "fixed missing import",
when: new Date("2020-05-10T09:18:42Z") when: new Date("2020-05-10T09:18:42Z"),
}; };
const commitImplementMain = { const commitImplementMain = {
revision: "5203292ab2bc0c020dd22adc4d3897da4930e43f", revision: "5203292ab2bc0c020dd22adc4d3897da4930e43f",
author: { author: {
name: "Ford Prefect", name: "Ford Prefect",
mail: "ford.prefect@hitchhiker.com" mail: "ford.prefect@hitchhiker.com",
}, },
description: "implemented main function", description: "implemented main function",
when: new Date("2020-04-12T16:29:42Z") when: new Date("2020-04-12T16:29:42Z"),
}; };
const source: AnnotatedSource = { const source: AnnotatedSource = {
@@ -72,44 +72,44 @@ const source: AnnotatedSource = {
{ {
lineNumber: 1, lineNumber: 1,
code: "package main", code: "package main",
...commitCreateNewApp ...commitCreateNewApp,
}, },
{ {
lineNumber: 2, lineNumber: 2,
code: "", code: "",
...commitCreateNewApp ...commitCreateNewApp,
}, },
{ {
lineNumber: 3, lineNumber: 3,
code: 'import "fmt"', code: 'import "fmt"',
...commitFixedMissingImport ...commitFixedMissingImport,
}, },
{ {
lineNumber: 4, lineNumber: 4,
code: "", code: "",
...commitFixedMissingImport ...commitFixedMissingImport,
}, },
{ {
lineNumber: 5, lineNumber: 5,
code: "func main() {", code: "func main() {",
...commitCreateNewApp ...commitCreateNewApp,
}, },
{ {
lineNumber: 6, lineNumber: 6,
code: ' fmt.Println("Hello World")', code: ' fmt.Println("Hello World")',
...commitImplementMain ...commitImplementMain,
}, },
{ {
lineNumber: 7, lineNumber: 7,
code: "}", code: "}",
...commitCreateNewApp ...commitCreateNewApp,
}, },
{ {
lineNumber: 8, lineNumber: 8,
code: "", code: "",
...commitCreateNewApp ...commitCreateNewApp,
} },
] ],
}; };
const markdownSource: AnnotatedSource = { const markdownSource: AnnotatedSource = {
@@ -118,44 +118,44 @@ const markdownSource: AnnotatedSource = {
{ {
lineNumber: 1, lineNumber: 1,
code: "# Title", code: "# Title",
...commitCreateNewApp ...commitCreateNewApp,
}, },
{ {
lineNumber: 2, lineNumber: 2,
code: "", code: "",
...commitCreateNewApp ...commitCreateNewApp,
}, },
{ {
lineNumber: 3, lineNumber: 3,
code: "This is a short Markdown text.", code: "This is a short Markdown text.",
...commitFixedMissingImport ...commitFixedMissingImport,
}, },
{ {
lineNumber: 4, lineNumber: 4,
code: "", code: "",
...commitFixedMissingImport ...commitFixedMissingImport,
}, },
{ {
lineNumber: 5, lineNumber: 5,
code: "With **bold** and __italic__ words.", code: "With **bold** and __italic__ words.",
...commitCreateNewApp ...commitCreateNewApp,
}, },
{ {
lineNumber: 6, lineNumber: 6,
code: "", code: "",
...commitImplementMain ...commitImplementMain,
}, },
{ {
lineNumber: 7, lineNumber: 7,
code: "> This should be a quote", code: "> This should be a quote",
...commitCreateNewApp ...commitCreateNewApp,
}, },
{ {
lineNumber: 8, lineNumber: 8,
code: "", code: "",
...commitCreateNewApp ...commitCreateNewApp,
} },
] ],
}; };
const Robohash: FC = ({ children }) => { const Robohash: FC = ({ children }) => {
@@ -165,8 +165,8 @@ const Robohash: FC = ({ children }) => {
}; };
storiesOf("Repositories/Annotate", module) storiesOf("Repositories/Annotate", module)
.addDecorator(storyFn => <MemoryRouter initialEntries={["/"]}>{storyFn()}</MemoryRouter>) .addDecorator((storyFn) => <MemoryRouter initialEntries={["/"]}>{storyFn()}</MemoryRouter>)
.addDecorator(storyFn => <Wrapper className="box">{storyFn()}</Wrapper>) .addDecorator((storyFn) => <Wrapper className="box">{storyFn()}</Wrapper>)
.add("Default", () => ( .add("Default", () => (
<Annotate source={source} repository={repository} baseDate={new Date("2020-04-16T09:22:42Z")} /> <Annotate source={source} repository={repository} baseDate={new Date("2020-04-16T09:22:42Z")} />
)) ))

View File

@@ -115,7 +115,7 @@ const Contributors: FC<PersonsProps> = ({ persons, label, displayTextOnly }) =>
<> <>
{t(label)}{" "} {t(label)}{" "}
<AvatarList> <AvatarList>
{persons.map(p => ( {persons.map((p) => (
<ContributorWithAvatar key={p.name} person={p} avatar={avatarFactory(p)} /> <ContributorWithAvatar key={p.name} person={p} avatar={avatarFactory(p)} />
))} ))}
</AvatarList> </AvatarList>
@@ -125,9 +125,9 @@ const Contributors: FC<PersonsProps> = ({ persons, label, displayTextOnly }) =>
return ( return (
<> <>
{t(label)}{" "} {t(label)}{" "}
<a title={persons.map(person => "- " + person.name).join("\n")}> <span title={persons.map((person) => "- " + person.name).join("\n")}>
{t("changeset.contributors.more", { count: persons.length })} {t("changeset.contributors.more", { count: persons.length })}
</a> </span>
</> </>
); );
} }
@@ -148,7 +148,7 @@ const ChangesetAuthor: FC<Props> = ({ changeset }) => {
const filterContributorsByType = (type: string) => { const filterContributorsByType = (type: string) => {
if (changeset.contributors) { if (changeset.contributors) {
return changeset.contributors.filter(p => p.type === type).map(contributor => contributor.person); return changeset.contributors.filter((p) => p.type === type).map((contributor) => contributor.person);
} }
return emptyListOfContributors; return emptyListOfContributors;
}; };

View File

@@ -39,11 +39,11 @@ const ChangesetDescription: FC<Props> = ({ changeset, value }) => {
"changeset.description.tokens", "changeset.description.tokens",
{ {
changeset, changeset,
value value,
} }
); );
return <SplitAndReplace text={value} replacements={replacements.flatMap(r => r(changeset, value))} />; return <SplitAndReplace text={value} replacements={replacements.flatMap((r) => r(changeset, value))} />;
}; };
export default ChangesetDescription; export default ChangesetDescription;

View File

@@ -29,9 +29,9 @@ describe("isDiffSupported tests", () => {
const supported = isDiffSupported({ const supported = isDiffSupported({
_links: { _links: {
diff: { diff: {
href: "http://diff" href: "http://diff",
} },
} },
}); });
expect(supported).toBe(true); expect(supported).toBe(true);
@@ -41,9 +41,9 @@ describe("isDiffSupported tests", () => {
const supported = isDiffSupported({ const supported = isDiffSupported({
_links: { _links: {
diffParsed: { diffParsed: {
href: "http://diff" href: "http://diff",
} },
} },
}); });
expect(supported).toBe(true); expect(supported).toBe(true);
@@ -51,7 +51,7 @@ describe("isDiffSupported tests", () => {
it("should return false if not diff link was provided", () => { it("should return false if not diff link was provided", () => {
const supported = isDiffSupported({ const supported = isDiffSupported({
_links: {} _links: {},
}); });
expect(supported).toBe(false); expect(supported).toBe(false);
@@ -63,9 +63,9 @@ describe("createUrl tests", () => {
const url = createUrl({ const url = createUrl({
_links: { _links: {
diff: { diff: {
href: "http://diff" href: "http://diff",
} },
} },
}); });
expect(url).toBe("http://diff?format=GIT"); expect(url).toBe("http://diff?format=GIT");
@@ -75,9 +75,9 @@ describe("createUrl tests", () => {
const url = createUrl({ const url = createUrl({
_links: { _links: {
diffParsed: { diffParsed: {
href: "http://diff-parsed" href: "http://diff-parsed",
} },
} },
}); });
expect(url).toBe("http://diff-parsed"); expect(url).toBe("http://diff-parsed");
@@ -87,12 +87,12 @@ describe("createUrl tests", () => {
const url = createUrl({ const url = createUrl({
_links: { _links: {
diff: { diff: {
href: "http://diff" href: "http://diff",
}, },
diffParsed: { diffParsed: {
href: "http://diff-parsed" href: "http://diff-parsed",
} },
} },
}); });
expect(url).toBe("http://diff-parsed"); expect(url).toBe("http://diff-parsed");
@@ -101,7 +101,7 @@ describe("createUrl tests", () => {
it("should throw an error if no diff link is defined", () => { it("should throw an error if no diff link is defined", () => {
expect(() => expect(() =>
createUrl({ createUrl({
_links: {} _links: {},
}) })
).toThrow(); ).toThrow();
}); });

Some files were not shown because too many files have changed in this diff Show More