• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gitify-app / gitify / 9319904199

31 May 2024 02:38PM UTC coverage: 96.355% (-0.4%) from 96.787%
9319904199

Pull #1139

github

web-flow
Merge af6de505a into 72b432272
Pull Request #1139: feat(accounts): enhance auth account data structure

402 of 415 branches covered (96.87%)

Branch coverage included in aggregate %.

79 of 89 new or added lines in 12 files covered. (88.76%)

3 existing lines in 2 files now uncovered.

1052 of 1094 relevant lines covered (96.16%)

20.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.15
/src/routes/LoginWithOAuthApp.tsx
1
import {
2✔
2
  ArrowLeftIcon,
3
  BookIcon,
4
  PersonIcon,
5
  SignInIcon,
6
} from '@primer/octicons-react';
7
import { type FC, useCallback, useContext } from 'react';
2✔
8
import { Form, type FormRenderProps } from 'react-final-form';
2✔
9
import { useNavigate } from 'react-router-dom';
2✔
10
import { Button } from '../components/fields/Button';
2✔
11
import { FieldInput } from '../components/fields/FieldInput';
2✔
12
import { AppContext } from '../context/App';
2✔
13
import type { LoginOAuthAppOptions } from '../utils/auth/types';
14
import {
2✔
15
  getNewOAuthAppURL,
16
  isValidClientId,
17
  isValidHostname,
18
  isValidToken,
19
} from '../utils/auth/utils';
20
import Constants from '../utils/constants';
2✔
21

22
interface IValues {
23
  hostname?: string;
24
  clientId?: string;
25
  clientSecret?: string;
26
}
27

28
interface IFormErrors {
29
  hostname?: string;
30
  clientId?: string;
31
  clientSecret?: string;
32
}
33

34
export const validate = (values: IValues): IFormErrors => {
2✔
35
  const errors: IFormErrors = {};
32✔
36

37
  if (!values.hostname) {
32✔
38
    errors.hostname = 'Required';
18✔
39
  } else if (!isValidHostname(values.hostname)) {
14✔
40
    errors.hostname = 'Invalid hostname.';
12✔
41
  }
42

43
  if (!values.clientId) {
32✔
44
    errors.clientId = 'Required';
22✔
45
  } else if (!isValidClientId(values.clientId)) {
10✔
46
    errors.clientId = 'Invalid client id.';
10✔
47
  }
48

49
  if (!values.clientSecret) {
32✔
50
    errors.clientSecret = 'Required';
24✔
51
  } else if (!isValidToken(values.clientSecret)) {
8✔
52
    errors.clientSecret = 'Invalid client secret.';
8✔
53
  }
54

55
  return errors;
32✔
56
};
57

58
export const LoginWithOAuthApp: FC = () => {
2✔
59
  const { loginWithOAuthApp } = useContext(AppContext);
12✔
60
  const navigate = useNavigate();
12✔
61

62
  const renderForm = (formProps: FormRenderProps) => {
12✔
63
    const { handleSubmit, submitting, pristine, values } = formProps;
34✔
64

65
    return (
34✔
66
      <form onSubmit={handleSubmit}>
67
        <FieldInput
68
          name="hostname"
69
          label="Hostname"
70
          placeholder="github.company.com"
71
          helpText={
72
            <div className="mb-1">
73
              <Button
74
                name="Create new OAuth App"
75
                label="Create new OAuth App"
76
                disabled={!values.hostname}
77
                icon={PersonIcon}
78
                size={12}
79
                url={getNewOAuthAppURL(values.hostname)}
80
              />{' '}
81
              on GitHub then paste your{' '}
82
              <span className="italic">client id and client secret</span> below.
83
            </div>
84
          }
85
        />
86

87
        <FieldInput name="clientId" label="Client ID" placeholder="123456789" />
88

89
        <FieldInput
90
          name="clientSecret"
91
          label="Client Secret"
92
          placeholder="ABC123DEF456"
93
        />
94

95
        <div className="flex justify-between items-end">
96
          <Button
97
            name="Docs"
98
            label="GitHub Docs"
99
            class="mt-2"
100
            icon={BookIcon}
101
            size={12}
102
            url={Constants.GITHUB_DOCS.OAUTH_URL}
103
          />
104

105
          <Button
106
            name="Login"
107
            label="Login"
108
            class="px-4 py-2 mt-2 !text-sm"
109
            icon={SignInIcon}
110
            size={16}
111
            disabled={submitting || pristine}
34✔
112
            type="submit"
113
          />
114
        </div>
115
      </form>
116
    );
117
  };
118

119
  const login = useCallback(async (data: IValues) => {
12✔
120
    try {
×
NEW
121
      await loginWithOAuthApp(data as LoginOAuthAppOptions);
×
122
    } catch (err) {
123
      // Skip
124
    }
125
  }, []);
126

127
  return (
12✔
128
    <div className="flex-1 bg-white dark:bg-gray-dark dark:text-white">
129
      <div className="flex justify-between items-center mt-4 py-2 mx-8">
130
        <button
131
          type="button"
132
          className="focus:outline-none"
133
          title="Go Back"
134
          onClick={() => navigate(-1)}
2✔
135
        >
136
          <ArrowLeftIcon
137
            size={20}
138
            className="hover:text-gray-400"
139
            aria-label="Go Back"
140
          />
141
        </button>
142

143
        <h3 className="text-lg font-semibold justify-center">
144
          <PersonIcon size={20} className="mr-2" />
145
          Login with OAuth App
146
        </h3>
147
      </div>
148

149
      <div className="flex-1 px-8">
150
        <Form
151
          initialValues={{
152
            hostname: '',
153
            clientId: '',
154
            clientSecret: '',
155
          }}
156
          onSubmit={login}
157
          validate={validate}
158
        >
159
          {renderForm}
160
        </Form>
161
      </div>
162
    </div>
163
  );
164
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc