Skip to content
This repository was archived by the owner on Jan 16, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": [
"@verdaccio",
"prettier",
"plugin:react/recommended",
"plugin:jest/recommended",
"plugin:prettier/recommended",
Expand Down
2 changes: 1 addition & 1 deletion i18n/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ i18n
// init i18next
// for all options read: https://www.i18next.com/overview/configuration-options
.init({
// in case window.VEDACCIO_LANGUAGE is undefined,it will fall back to 'en-US'
// in case window.__VERDACCIO_BASENAME_UI_OPTIONS.language is undefined,it will fall back to 'en-US'
lng: window?.__VERDACCIO_BASENAME_UI_OPTIONS?.language || 'en-US',
fallbackLng: 'en-US',
whitelist: [
Expand Down
2 changes: 2 additions & 0 deletions jest/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module.exports = {
'<rootDir>/scripts',
'<rootDir>/.circleci',
'<rootDir>/tools',
'<rootDir>/jest',
'<rootDir>/build',
'<rootDir>/.vscode/',
'<rootDir>/test/e2e/',
Expand All @@ -28,6 +29,7 @@ module.exports = {
// note: this section has to be on sync with webpack configuration
'verdaccio-ui/components/(.*)': '<rootDir>/src/components/$1',
'verdaccio-ui/utils/(.*)': '<rootDir>/src/utils/$1',
'verdaccio-ui/providers/(.*)': '<rootDir>/src/providers/$1',
'verdaccio-ui/design-tokens/(.*)': '<rootDir>/src/design-tokens/$1',
},
};
18 changes: 13 additions & 5 deletions jest/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@
import { GlobalWithFetchMock } from 'jest-fetch-mock';
import 'mutationobserver-shim';

// @ts-ignore : Property '__APP_VERSION__' does not exist on type 'Global'.
global.__APP_VERSION__ = '1.0.0';
// @ts-ignore : Property '__VERDACCIO_BASENAME_UI_OPTIONS' does not exist on type 'Global'.
global.__VERDACCIO_BASENAME_UI_OPTIONS = { base: 'http://localhost' };
// @ts-ignore : Property 'VERDACCIO_API_URL' does not exist on type 'Global'.
global.VERDACCIO_API_URL = 'https://verdaccio.tld';
global.__VERDACCIO_BASENAME_UI_OPTIONS = {
base: 'http://localhost',
protocol: 'http',
host: 'localhost',
primaryColor: '#4b5e40',
url_prefix: '',
darkMode: false,
language: 'en-US',
uri: 'http://localhost:4872',
title: 'Verdaccio Dev UI',
scope: '',
version: 'v1.0.0',
};

const customGlobal: GlobalWithFetchMock = global as GlobalWithFetchMock;
customGlobal.fetch = require('jest-fetch-mock');
Expand Down
8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@
"emotion": "10.0.27",
"emotion-theming": "10.0.27",
"eslint": "7.15.0",
"eslint-config-prettier": "7.2.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-codeceptjs": "1.3.0",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-prettier": "3.2.0",
"eslint-plugin-react": "7.21.5",
"eslint-plugin-react-hooks": "4.2.0",
"eslint-plugin-verdaccio": "9.6.1",
Expand Down Expand Up @@ -153,7 +153,7 @@
"typescript": "3.9.6",
"url-loader": "^4.1.1",
"validator": "13.1.1",
"verdaccio": "4.8.1",
"verdaccio": "4.11.3",
"verdaccio-auth-memory": "9.7.2",
"verdaccio-memory": "9.7.2",
"wait-on": "5.2.0",
Expand Down Expand Up @@ -212,11 +212,9 @@
},
"lint-staged": {
"*.{js,tsx,ts}": [
"eslint . --ext .js,.ts,.tsx",
"prettier --write"
"eslint . --ext .js,.ts,.tsx"
],
"*": [
"detect-secrets-launcher --baseline .secrets-baseline --word-list",
"git add"
]
},
Expand Down
Binary file added partials/storage/jquery/jquery-3.3.1.tgz
Binary file not shown.
4 changes: 2 additions & 2 deletions partials/storage/jquery/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4981,7 +4981,7 @@
"shasum": "958ce29e81c9790f31be7792df5d4d95fc57fbca"
}
},
"_rev": "61-e6be890a78963127",
"_rev": "63-5c66112fe65cff7d",
"readme": "# jQuery\n\n> jQuery is a fast, small, and feature-rich JavaScript library.\n\nFor information on how to get started and how to use jQuery, please see [jQuery's documentation](http://api.jquery.com/).\nFor source files and issues, please visit the [jQuery repo](https://github.com/jquery/jquery).\n\nIf upgrading, please see the [blog post for 3.3.1](https://blog.jquery.com/2017/03/20/jquery-3.3.1-now-available/). This includes notable differences from the previous version and a more readable changelog.\n\n## Including jQuery\n\nBelow are some of the most common ways to include jQuery.\n\n### Browser\n\n#### Script tag\n\n```html\n<script src=\"https://code.jquery.com/jquery-3.3.1.min.js\"></script>\n```\n\n#### Babel\n\n[Babel](http://babeljs.io/) is a next generation JavaScript compiler. One of the features is the ability to use ES6/ES2015 modules now, even though browsers do not yet support this feature natively.\n\n```js\nimport $ from \"jquery\";\n```\n\n#### Browserify/Webpack\n\nThere are several ways to use [Browserify](http://browserify.org/) and [Webpack](https://webpack.github.io/). For more information on using these tools, please refer to the corresponding project's documention. In the script, including jQuery will usually look like this...\n\n```js\nvar $ = require(\"jquery\");\n```\n\n#### AMD (Asynchronous Module Definition)\n\nAMD is a module format built for the browser. For more information, we recommend [require.js' documentation](http://requirejs.org/docs/whyamd.html).\n\n```js\ndefine([\"jquery\"], function($) {\n\n});\n```\n\n### Node\n\nTo include jQuery in [Node](nodejs.org), first install with npm.\n\n```sh\nnpm install jquery\n```\n\nFor jQuery to work in Node, a window with a document is required. Since no such window exists natively in Node, one can be mocked by tools such as [jsdom](https://github.com/tmpvar/jsdom). This can be useful for testing purposes.\n\n```js\nrequire(\"jsdom\").env(\"\", function(err, window) {\n\tif (err) {\n\t\tconsole.error(err);\n\t\treturn;\n\t}\n\n\tvar $ = require(\"jquery\")(window);\n});\n```",
"_id": "jquery"
}
}
2 changes: 1 addition & 1 deletion src/App/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jest.mock('verdaccio-ui/utils/storage', () => {
return new LocalStorageMock();
});

jest.mock('verdaccio-ui/utils/api', () => ({
jest.mock('verdaccio-ui/providers/API/api', () => ({
// eslint-disable-next-line jest/no-mocks-import
request: require('../../jest/unit/components/__mocks__/api').default.request,
}));
Expand Down
2 changes: 1 addition & 1 deletion src/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const StyledBoxContent = styled(Box)<{ theme?: Theme }>(({ theme }) => ({
/* eslint-disable react/jsx-no-bind */
/* eslint-disable react-hooks/exhaustive-deps */
const App: React.FC = () => {
const [user, setUser] = useState<undefined | { username: string }>();
const [user, setUser] = useState<undefined | { username: string | null }>();
/**
* Logout user
* Required by: <Header />
Expand Down
2 changes: 1 addition & 1 deletion src/App/AppContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface AppProps {
}

export interface User {
username: string;
username: string | null;
}

export interface AppContextProps extends AppProps {
Expand Down
5 changes: 4 additions & 1 deletion src/App/AppContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, { useState, useEffect } from 'react';

import { useConfig } from 'verdaccio-ui/providers/config';

import AppContext, { AppProps, User } from './AppContext';

interface Props {
Expand All @@ -8,8 +10,9 @@ interface Props {

/* eslint-disable react-hooks/exhaustive-deps */
const AppContextProvider: React.FC<Props> = ({ children, user }) => {
const { configOptions } = useConfig();
const [state, setState] = useState<AppProps>({
scope: window.VERDACCIO_SCOPE || '',
scope: configOptions.scope ?? '',
user,
});

Expand Down
5 changes: 2 additions & 3 deletions src/App/AppRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ enum Route {
}

export const history = createBrowserHistory({
// @ts-ignore
basename: window.__VERDACCIO_BASENAME_UI_OPTIONS && window.__VERDACCIO_BASENAME_UI_OPTIONS.url_prefix,
basename: window?.__VERDACCIO_BASENAME_UI_OPTIONS?.url_prefix,
});

const AppRoute: React.FC = () => {
Expand All @@ -36,7 +35,7 @@ const AppRoute: React.FC = () => {

const { user } = appContext;

const isUserLoggedIn = user && user.username;
const isUserLoggedIn = user?.username;

return (
<Router history={history}>
Expand Down
4 changes: 2 additions & 2 deletions src/App/Footer/Footer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import Footer from './Footer';

describe('<Footer /> component', () => {
beforeAll(() => {
window.VERDACCIO_VERSION = 'v.1.0.0';
window.__VERDACCIO_BASENAME_UI_OPTIONS.version = 'v.1.0.0';
});

afterAll(() => {
delete window.VERDACCIO_VERSION;
delete window.__VERDACCIO_BASENAME_UI_OPTIONS.version;
});

test('should load the initial state of Footer component', () => {
Expand Down
12 changes: 9 additions & 3 deletions src/App/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { useTranslation, Trans } from 'react-i18next';
import { Austria, Brazil, Earth, Nicaragua, Spain, Germany, India, China, Taiwan } from 'verdaccio-ui/components/Icons';
import Logo from 'verdaccio-ui/components/Logo';
import { Theme } from 'verdaccio-ui/design-tokens/theme';
import { useConfig } from 'verdaccio-ui/providers/config';
import { goToVerdaccioWebsite } from 'verdaccio-ui/utils/windows';

import { Wrapper, Left, Right, Love, Inner } from './styles';

/* eslint-disable react/jsx-key */
const Footer = () => {
const { t } = useTranslation();
const { configOptions } = useConfig();
return (
<Wrapper>
<Inner>
Expand All @@ -32,9 +34,13 @@ const Footer = () => {
</ToolTip>
</Left>
<Right>
{t('footer.powered-by')}
<Logo onClick={goToVerdaccioWebsite} size="x-small" />
{`/ ${window.VERDACCIO_VERSION}`}
{configOptions?.version && (
<>
{t('footer.powered-by')}
<Logo onClick={goToVerdaccioWebsite} size="x-small" />
{`/ ${configOptions.version}`}
</>
)}
</Right>
</Inner>
</Wrapper>
Expand Down
7 changes: 4 additions & 3 deletions src/App/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React, { useState, useContext } from 'react';
import { useTranslation } from 'react-i18next';

import Button from 'verdaccio-ui/components/Button';
import { useConfig } from 'verdaccio-ui/providers/config';
import storage from 'verdaccio-ui/utils/storage';
import { getRegistryURL } from 'verdaccio-ui/utils/url';

import AppContext from '../../App/AppContext';

Expand Down Expand Up @@ -31,6 +31,7 @@ const Header: React.FC<Props> = ({ withoutSearch }) => {
}

const { user, scope, setUser } = appContext;
const { configOptions } = useConfig();

/**
* Logouts user
Expand All @@ -52,14 +53,14 @@ const Header: React.FC<Props> = ({ withoutSearch }) => {
onOpenRegistryInfoDialog={() => setOpenInfoDialog(true)}
onToggleLogin={() => setShowLoginModal(!showLoginModal)}
onToggleMobileNav={() => setShowMobileNavBar(!showMobileNavBar)}
username={user && user.username}
username={user?.username}
withoutSearch={withoutSearch}
/>
</InnerNavBar>
<HeaderInfoDialog
isOpen={isInfoDialogOpen}
onCloseDialog={() => setOpenInfoDialog(false)}
registryUrl={getRegistryURL()}
registryUrl={configOptions.base}
scope={scope}
/>
</NavBar>
Expand Down
2 changes: 1 addition & 1 deletion src/App/Header/HeaderRight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { RightSide } from './styles';

interface Props {
withoutSearch?: boolean;
username?: string;
username?: string | null;
onToggleLogin: () => void;
onOpenRegistryInfoDialog: () => void;
onToggleMobileNav: () => void;
Expand Down
24 changes: 16 additions & 8 deletions src/App/Header/LoginDialog/LoginDialog.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';

import api from 'verdaccio-ui/utils/api';
import { render, waitFor, fireEvent } from 'verdaccio-ui/utils/test-react-testing-library';
import api from 'verdaccio-ui/providers/API/api';
import { render, waitFor, fireEvent, cleanup, act } from 'verdaccio-ui/utils/test-react-testing-library';

import AppContext, { AppContextProps } from '../../AppContext';

Expand All @@ -16,6 +16,7 @@ describe('<LoginDialog /> component', () => {
beforeEach(() => {
jest.resetModules();
jest.resetAllMocks();
cleanup();
});

test('should render the component in default state', () => {
Expand Down Expand Up @@ -61,12 +62,13 @@ describe('<LoginDialog /> component', () => {
const loginDialogButton = await waitFor(() => getByTestId('close-login-dialog-button'));
expect(loginDialogButton).toBeTruthy();

fireEvent.click(loginDialogButton, { open: false });
act(() => {
fireEvent.click(loginDialogButton, { open: false });
});
expect(props.onClose).toHaveBeenCalled();
});

// TODO
test.skip('setCredentials - should set username and password in state', async () => {
test('setCredentials - should set username and password in state', async () => {
const props = {
open: true,
onClose: jest.fn(),
Expand All @@ -79,25 +81,31 @@ describe('<LoginDialog /> component', () => {
})
);

const { getByPlaceholderText, getByText } = render(
const { getByPlaceholderText, getByTestId } = render(
<AppContext.Provider value={appContextValue}>
<LoginDialog onClose={props.onClose} open={props.open} />
</AppContext.Provider>
);

// TODO: the input's value is not being updated in the DOM
const userNameInput = getByPlaceholderText('Your username');

fireEvent.focus(userNameInput);

fireEvent.change(userNameInput, { target: { value: 'xyz' } });

// TODO: the input's value is not being updated in the DOM
const passwordInput = getByPlaceholderText('Your strong password');

fireEvent.focus(passwordInput);
fireEvent.change(passwordInput, { target: { value: '1234' } });

// TODO: submitting form does not work
const signInButton = getByText('Sign in');
fireEvent.click(signInButton);
const signInButton = getByTestId('login-dialog-form-login-button');
expect(signInButton).not.toBeDisabled();
act(() => {
fireEvent.click(signInButton);
});
});

test.todo('validateCredentials: should validate credentials');
Expand Down
35 changes: 33 additions & 2 deletions src/App/Header/LoginDialog/LoginDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import i18next from 'i18next';
import isEmpty from 'lodash/isEmpty';
import React, { useState, useContext, useCallback } from 'react';
import { useTranslation } from 'react-i18next';

import Dialog from 'verdaccio-ui/components/Dialog';
import DialogContent from 'verdaccio-ui/components/DialogContent';
import { makeLogin, LoginError } from 'verdaccio-ui/utils/login';
import { useAPI, LoginBody } from 'verdaccio-ui/providers/API/APIProvider';
import { LoginError } from 'verdaccio-ui/utils/login';
import storage from 'verdaccio-ui/utils/storage';

import AppContext from '../../../App/AppContext';
Expand All @@ -20,6 +23,34 @@ interface Props {
const LoginDialog: React.FC<Props> = ({ onClose, open = false }) => {
const { t } = useTranslation();
const appContext = useContext(AppContext);
const { doLogin } = useAPI();

const makeLogin = useCallback(
async (username?: string, password?: string): Promise<LoginBody> => {
// checks isEmpty
if (isEmpty(username) || isEmpty(password)) {
const error = {
type: 'error',
description: i18next.t('form-validation.username-or-password-cant-be-empty'),
};
return { error };
}

try {
const response: LoginBody = await doLogin(username as string, password as string);

return response;
} catch (e) {
console.error('login error', e.message);
const error = {
type: 'error',
description: i18next.t('form-validation.unable-to-sign-in'),
};
return { error };
}
},
[doLogin]
);

if (!appContext) {
throw Error(t('app-context-not-correct-used'));
Expand All @@ -42,7 +73,7 @@ const LoginDialog: React.FC<Props> = ({ onClose, open = false }) => {
onClose();
}
},
[appContext, onClose]
[appContext, onClose, makeLogin]
);

return (
Expand Down
Loading