chore(deps): upgrade storybook to v8 (#5056)
* chore(deps): upgrade storybook to v8 * Update
This commit is contained in:
5
.changeset/short-mails-smoke.md
Normal file
5
.changeset/short-mails-smoke.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@verdaccio/ui-components': patch
|
||||
---
|
||||
|
||||
chore(deps): upgrade storybook to v8
|
||||
2
.github/workflows/ui-components.yml
vendored
2
.github/workflows/ui-components.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
- name: Install pnpm
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare
|
||||
corepack install
|
||||
- name: Install
|
||||
run: pnpm install
|
||||
- name: Build storybook
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.storybook
|
||||
public/
|
||||
msw
|
||||
jest
|
||||
vitest
|
||||
__snapshots__
|
||||
*.map
|
||||
|
||||
41
packages/ui-components/.storybook/i18n/index.ts
Normal file
41
packages/ui-components/.storybook/i18n/index.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import * as Flags from 'country-flag-icons/react/3x2';
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
const DEFAULT_LANGUAGE = 'en-US';
|
||||
|
||||
export const listLanguages = [
|
||||
{ lng: DEFAULT_LANGUAGE, icon: Flags.US, menuKey: 'lng.english' },
|
||||
{ lng: 'cs-CZ', icon: Flags.CZ, menuKey: 'lng.czech' },
|
||||
{ lng: 'pt-BR', icon: Flags.BR, menuKey: 'lng.portuguese' },
|
||||
{ lng: 'es-ES', icon: Flags.ES, menuKey: 'lng.spanish' },
|
||||
{ lng: 'de-DE', icon: Flags.DE, menuKey: 'lng.german' },
|
||||
];
|
||||
|
||||
const whitelist = listLanguages.reduce((acc, item) => {
|
||||
acc.push(item.lng);
|
||||
return acc;
|
||||
}, [] as string[]);
|
||||
|
||||
const resources = listLanguages.reduce((acc, item) => {
|
||||
// Use English for all languages
|
||||
acc[item.lng] = { translation: require(`./ui.json`) };
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
i18n.use(initReactI18next).init({
|
||||
lng: DEFAULT_LANGUAGE,
|
||||
fallbackLng: DEFAULT_LANGUAGE,
|
||||
whitelist,
|
||||
load: 'currentOnly',
|
||||
react: {
|
||||
useSuspense: false,
|
||||
},
|
||||
resources,
|
||||
debug: false,
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
206
packages/ui-components/.storybook/i18n/ui.json
Normal file
206
packages/ui-components/.storybook/i18n/ui.json
Normal file
@@ -0,0 +1,206 @@
|
||||
{
|
||||
"copy-to-clipboard": "Copy to clipboard",
|
||||
"author-anonymous": "Anonymous",
|
||||
"author-unknown": "Unknown",
|
||||
"action-bar-action": {
|
||||
"visit-home-page": "Visit homepage",
|
||||
"open-an-issue": "Open an issue",
|
||||
"download-tarball": "Download tarball",
|
||||
"raw": "View manifest",
|
||||
"raw-title": "Manifest of {{package}}"
|
||||
},
|
||||
"dialog": {
|
||||
"registry-info": {
|
||||
"title": "Information"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Configuration"
|
||||
},
|
||||
"license": "License",
|
||||
"totalContributors": "Total contributors"
|
||||
},
|
||||
"header": {
|
||||
"documentation": "Documentation",
|
||||
"registry-info": "Registry Information",
|
||||
"registry-info-link": "Learn more",
|
||||
"settings": "Settings",
|
||||
"help": "Help",
|
||||
"registry-no-conf": "No configurations available",
|
||||
"greetings": "Hi "
|
||||
},
|
||||
"search": {
|
||||
"packages": "Search Packages",
|
||||
"isPrivate": "Private",
|
||||
"isRemote": "Remote",
|
||||
"isCached": "Cached"
|
||||
},
|
||||
"autoComplete": {
|
||||
"loading": "Loading...",
|
||||
"no-results-found": "No results found",
|
||||
"clear": "Clear",
|
||||
"expand": "Expand",
|
||||
"collapse": "Collapse"
|
||||
},
|
||||
"tab": {
|
||||
"uplinks": "Uplinks",
|
||||
"versions": "Versions",
|
||||
"dependencies": "Dependencies",
|
||||
"readme": "Readme"
|
||||
},
|
||||
"uplinks": {
|
||||
"title": "Uplinks",
|
||||
"no-items": "{{name}} has no uplinks."
|
||||
},
|
||||
"versions": {
|
||||
"current-tags": "Current Tags",
|
||||
"version-history": "Version History",
|
||||
"not-available": "Not available",
|
||||
"deprecated": "Deprecated",
|
||||
"search.placeholder": "Search for a version by semver range, e.g., ^1.0.0.",
|
||||
"hide-deprecated": "All deprecated versions are hidden by global configuration"
|
||||
},
|
||||
"package": {
|
||||
"published-on": "Published {{time}}",
|
||||
"version": "v{{version}}",
|
||||
"visit-home-page": "Visit homepage",
|
||||
"homepage": "Homepage",
|
||||
"open-an-issue": "Open an issue",
|
||||
"bugs": "Bugs",
|
||||
"download": "Download {{what}}",
|
||||
"the-tar-file": "the tar file",
|
||||
"tarball": "Tarball"
|
||||
},
|
||||
"dependencies": {
|
||||
"has-no-dependencies": "{{package}} has no dependencies.",
|
||||
"dependency-block": "{{package}}: {{version}}",
|
||||
"dependency-block-bundle": "{{package}}"
|
||||
},
|
||||
"form": {
|
||||
"username": "Username",
|
||||
"password": "Password"
|
||||
},
|
||||
"form-placeholder": {
|
||||
"username": "Your username",
|
||||
"password": "Your strong password"
|
||||
},
|
||||
"form-validation": {
|
||||
"required-field": "This field is required",
|
||||
"required-min-length": "This field required with a minimum length of {{length}}",
|
||||
"unable-to-sign-in": "Unable to sign in",
|
||||
"username-or-password-cant-be-empty": "Username or password can't be empty!"
|
||||
},
|
||||
"help": {
|
||||
"title": "No Package Published Yet.",
|
||||
"sub-title": "To publish your first package just:",
|
||||
"first-step": "1. Create user",
|
||||
"first-step-command-line": "npm adduser --registry {{registryUrl}}",
|
||||
"second-step": "2. Publish",
|
||||
"second-step-command-line": "npm publish --registry {{registryUrl}}",
|
||||
"third-step": "3. Refresh this page"
|
||||
},
|
||||
"sidebar": {
|
||||
"detail": {
|
||||
"latest-version": "Latest v{{version}}",
|
||||
"version": "v{{version}}",
|
||||
"published": "Published"
|
||||
},
|
||||
"installation": {
|
||||
"title": "Installation",
|
||||
"latest": "latest version",
|
||||
"global": "global package",
|
||||
"yarnModern": "yarn modern syntax"
|
||||
},
|
||||
"repository": {
|
||||
"title": "Repository"
|
||||
},
|
||||
"author": {
|
||||
"title": "Author"
|
||||
},
|
||||
"distribution": {
|
||||
"title": "Distribution",
|
||||
"license": "License",
|
||||
"size": "Size",
|
||||
"file-count": "File Count"
|
||||
},
|
||||
"keywords": {
|
||||
"title": "Keywords"
|
||||
},
|
||||
"maintainers": {
|
||||
"title": "Maintainers"
|
||||
},
|
||||
"contributors": {
|
||||
"title": "Contributors"
|
||||
},
|
||||
"engines": {
|
||||
"npm-version": "Npm Version",
|
||||
"pnpm-version": "Pnpm Version",
|
||||
"yarn-version": "Yarn Version",
|
||||
"node-js": "Node.js"
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"powered-by": "Powered by",
|
||||
"made-with-love-on": "Made with <0>♥</0> on"
|
||||
},
|
||||
"button": {
|
||||
"close": "Close",
|
||||
"cancel": "Cancel",
|
||||
"login": "Login",
|
||||
"logout": "Logout",
|
||||
"go-to-the-home-page": "Go to the home page",
|
||||
"learn-more": "Learn More",
|
||||
"fund-this-package": "<0>Fund</0> this package"
|
||||
},
|
||||
"error": {
|
||||
"unspecific": "Something went wrong.",
|
||||
"404": {
|
||||
"sorry-we-could-not-find-it": "Sorry, we couldn't find it..."
|
||||
},
|
||||
"401": {
|
||||
"sorry-no-access": "Sorry, you need credentials access to see this page."
|
||||
},
|
||||
"app-context-not-correct-used": "The app context was not used correctly",
|
||||
"theme-context-not-correct-used": "The theme context was not used correctly",
|
||||
"package-meta-is-required-at-detail-context": "packageMeta is required at DetailContext"
|
||||
},
|
||||
"lng": {
|
||||
"english": "English",
|
||||
"czech": "Czech",
|
||||
"japanese": "Japanese",
|
||||
"portuguese": "Portuguese",
|
||||
"spanish": "Spanish",
|
||||
"irish": "Irish",
|
||||
"german": "German",
|
||||
"italian": "Italian",
|
||||
"french": "French",
|
||||
"russian": "Russian",
|
||||
"turkish": "Turkish",
|
||||
"ukraine": "Ukraine",
|
||||
"khmer": "Khmer",
|
||||
"chinese": "Chinese Simplified",
|
||||
"chineseTraditional": "Chinese Traditional"
|
||||
},
|
||||
"flag": {
|
||||
"austria": "Austria",
|
||||
"australia": "Australia",
|
||||
"brazil": "Brazil",
|
||||
"canada": "Canada",
|
||||
"spain": "Spain",
|
||||
"nicaragua": "Nicaragua",
|
||||
"india": "India",
|
||||
"china": "China",
|
||||
"germany": "Germany",
|
||||
"taiwan": "Taiwan"
|
||||
},
|
||||
"packageManagers": {
|
||||
"title": "Package Managers",
|
||||
"description": "This is the configuration details for the registry. Each package manager could have different configuration, expand each section for more details. If the section is disable review your configuration.",
|
||||
"yarnclassicDetails": "Yarn classic configuration differs from Yarn 2+ configuration. For more details, please visit [Yarn Classic](https://verdaccio.org/docs/cli-registry#yarn-1x).",
|
||||
"yarnBerryDetails": "Yarn Berry does not support the `--registry` flag, instead all configurarion should be defined on the `yarnrc.yaml` file in the root of your project. For more details, please visit [Yarn Berry](https://verdaccio.org/docs/cli-registry#yarn-berry-2x)."
|
||||
},
|
||||
"language": {
|
||||
"title": "Translations",
|
||||
"contribute": "If your language is not listed here or is not fully translated, please contribute to the translation. You can find the source code on [our main repository](https://github.com/verdaccio/verdaccio/blob/master/packages/plugins/ui-theme/src/i18n/ABOUT_TRANSLATIONS.md)",
|
||||
"description": "This is the configuration details for the language. Select a language to select a client side translation."
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
module.exports = {
|
||||
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
|
||||
addons: [
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@storybook/addon-interactions',
|
||||
],
|
||||
framework: '@storybook/react',
|
||||
layout: 'centered',
|
||||
core: {
|
||||
builder: 'webpack5',
|
||||
},
|
||||
};
|
||||
25
packages/ui-components/.storybook/main.ts
Normal file
25
packages/ui-components/.storybook/main.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { StorybookConfig } from '@storybook/react-webpack5';
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
||||
|
||||
addons: [
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@storybook/addon-interactions',
|
||||
'@storybook/addon-webpack5-compiler-babel',
|
||||
],
|
||||
|
||||
framework: {
|
||||
name: '@storybook/react-webpack5',
|
||||
options: {},
|
||||
},
|
||||
|
||||
staticDirs: ['../public'],
|
||||
|
||||
typescript: {
|
||||
reactDocgen: 'react-docgen-typescript',
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -1,10 +1,12 @@
|
||||
<script>
|
||||
window.__VERDACCIO_BASENAME_UI_OPTIONS = {
|
||||
"title": "Verdaccio Local Dev",
|
||||
"sort_packages": "asc", "primary_color": null,
|
||||
"pkgManagers": ["npm", "yarn", "pnpm"],
|
||||
"version": "1.0.0", "flags": { "searchRemote": true },
|
||||
"filename": "index.html",
|
||||
"base": "http://localhost:9000/"
|
||||
}
|
||||
</script>
|
||||
window.__VERDACCIO_BASENAME_UI_OPTIONS = {
|
||||
title: 'Verdaccio Local Dev',
|
||||
sort_packages: 'asc',
|
||||
primary_color: null,
|
||||
pkgManagers: ['npm', 'yarn', 'pnpm'],
|
||||
version: '1.0.0',
|
||||
flags: { searchRemote: true },
|
||||
filename: 'index.html',
|
||||
base: 'http://localhost:9000/',
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
import Flags from 'country-flag-icons/react/3x2';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import config from '../../plugins/ui-theme/src/i18n/config';
|
||||
import {
|
||||
AppConfigurationProvider,
|
||||
PersistenceSettingProvider,
|
||||
StyleBaseline,
|
||||
ThemeProvider,
|
||||
TranslatorProvider,
|
||||
store,
|
||||
} from '../src/';
|
||||
|
||||
const DEFAULT_LANGUAGE = 'en-US';
|
||||
const listLanguages = [
|
||||
{ lng: DEFAULT_LANGUAGE, icon: Flags.US, menuKey: 'lng.english' },
|
||||
{ lng: 'cs-CZ', icon: Flags.CZ, menuKey: 'lng.czech' },
|
||||
{ lng: 'pt-BR', icon: Flags.BR, menuKey: 'lng.portuguese' },
|
||||
{ lng: 'es-ES', icon: Flags.ES, menuKey: 'lng.spanish' },
|
||||
{ lng: 'de-DE', icon: Flags.DE, menuKey: 'lng.german' },
|
||||
];
|
||||
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: '^on[A-Z].*' },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// preview-head file contains the __VERDACCIO_BASENAME_UI_OPTIONS
|
||||
// required by AppConfigurationProvider
|
||||
export const withMuiTheme = (Story) => (
|
||||
<Provider store={store}>
|
||||
<TranslatorProvider onMount={() => {}} i18n={config} listLanguages={listLanguages}>
|
||||
<PersistenceSettingProvider>
|
||||
<AppConfigurationProvider>
|
||||
<ThemeProvider>
|
||||
<StyleBaseline />
|
||||
<Story />
|
||||
</ThemeProvider>
|
||||
</AppConfigurationProvider>
|
||||
</PersistenceSettingProvider>
|
||||
</TranslatorProvider>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
if (typeof global.process === 'undefined') {
|
||||
const { worker } = require('../msw/browser');
|
||||
worker.start();
|
||||
}
|
||||
|
||||
export const decorators = [withMuiTheme];
|
||||
55
packages/ui-components/.storybook/preview.tsx
Normal file
55
packages/ui-components/.storybook/preview.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import type { Preview, StoryFn } from '@storybook/react';
|
||||
import { initialize, mswLoader } from 'msw-storybook-addon';
|
||||
import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import {
|
||||
AppConfigurationProvider,
|
||||
PersistenceSettingProvider,
|
||||
StyleBaseline,
|
||||
ThemeProvider,
|
||||
TranslatorProvider,
|
||||
store,
|
||||
} from '../src';
|
||||
import i18n, { listLanguages } from './i18n';
|
||||
|
||||
// preview-head file contains the __VERDACCIO_BASENAME_UI_OPTIONS
|
||||
// required by AppConfigurationProvider
|
||||
export const withMuiTheme = (Story: StoryFn) => (
|
||||
<Provider store={store}>
|
||||
<TranslatorProvider onMount={() => ({})} i18n={i18n} listLanguages={listLanguages}>
|
||||
<PersistenceSettingProvider>
|
||||
<AppConfigurationProvider>
|
||||
<ThemeProvider>
|
||||
<StyleBaseline />
|
||||
<Story />
|
||||
</ThemeProvider>
|
||||
</AppConfigurationProvider>
|
||||
</PersistenceSettingProvider>
|
||||
</TranslatorProvider>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
/*
|
||||
* Initializes MSW
|
||||
*/
|
||||
initialize();
|
||||
|
||||
/*
|
||||
* Setup the preview
|
||||
*/
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
actions: { argTypesRegex: '^on[A-Z].*' },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/,
|
||||
},
|
||||
},
|
||||
},
|
||||
decorators: [withMuiTheme],
|
||||
loaders: [mswLoader],
|
||||
};
|
||||
|
||||
export default preview;
|
||||
@@ -1,5 +0,0 @@
|
||||
import { setupWorker } from 'msw';
|
||||
|
||||
import { handlers } from '../jest/server-handlers';
|
||||
|
||||
export const worker = setupWorker(...handlers);
|
||||
@@ -16,8 +16,8 @@
|
||||
"watch": "babel src/ --out-dir build/ --watch --copy-files --no-copy-ignored --extensions \".ts,.tsx\" --source-maps --ignore \"src/**/*.stories.tsx\" --ignore \"src/**/*.test.tsx\" --ignore \"src/**/*.test.ts\"",
|
||||
"build": "pnpm run build:js && pnpm run build:types",
|
||||
"netlify:ui:deploy": "npx netlify-cli deploy --dir=./packages/ui-components/storybook-static --prod",
|
||||
"start": "start-storybook -p 6006 -s ./public",
|
||||
"build-storybook": "build-storybook"
|
||||
"start": "storybook dev -p 6006",
|
||||
"build-storybook": "storybook build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "11.11.4",
|
||||
@@ -60,13 +60,13 @@
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.26.0",
|
||||
"@emotion/babel-plugin": "11.12.0",
|
||||
"@storybook/addon-actions": "^6.5.15",
|
||||
"@storybook/addon-essentials": "^6.5.15",
|
||||
"@storybook/addon-interactions": "^6.5.15",
|
||||
"@storybook/addon-links": "^6.5.15",
|
||||
"@storybook/builder-webpack5": "^6.5.15",
|
||||
"@storybook/manager-webpack5": "^6.5.15",
|
||||
"@storybook/react": "^6.5.15",
|
||||
"@storybook/addon-actions": "^8.4.7",
|
||||
"@storybook/addon-essentials": "^8.4.7",
|
||||
"@storybook/addon-interactions": "^8.4.7",
|
||||
"@storybook/addon-links": "^8.4.7",
|
||||
"@storybook/addon-webpack5-compiler-babel": "3.0.5",
|
||||
"@storybook/react": "^8.4.7",
|
||||
"@storybook/react-webpack5": "8.4.7",
|
||||
"@testing-library/dom": "10.4.0",
|
||||
"@testing-library/jest-dom": "6.6.3",
|
||||
"@testing-library/react": "16.1.0",
|
||||
@@ -75,16 +75,20 @@
|
||||
"@types/unist": "^2.0.0",
|
||||
"@verdaccio/types": "workspace:13.0.0-next-8.2",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"jsdom": "^25.0.0",
|
||||
"babel-loader": "9.2.1",
|
||||
"jsdom": "^25.0.0",
|
||||
"mockdate": "3.0.5",
|
||||
"msw": "2.7.0",
|
||||
"msw-storybook-addon": "^2.0.4",
|
||||
"mutationobserver-shim": "0.3.7",
|
||||
"msw": "0.49.3",
|
||||
"storybook": "8.4.7",
|
||||
"typescript": "4.9.5",
|
||||
"vitest": "3.0.4",
|
||||
"whatwg-fetch": "3.6.20"
|
||||
},
|
||||
"msw": {
|
||||
"workerDirectory": "public"
|
||||
"workerDirectory": [
|
||||
"public"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
BIN
packages/ui-components/public/favicon.ico
Normal file
BIN
packages/ui-components/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -2,13 +2,15 @@
|
||||
/* tslint:disable */
|
||||
|
||||
/**
|
||||
* Mock Service Worker (0.49.2).
|
||||
* Mock Service Worker.
|
||||
* @see https://github.com/mswjs/msw
|
||||
* - Please do NOT modify this file.
|
||||
* - Please do NOT serve this file on production.
|
||||
*/
|
||||
|
||||
const INTEGRITY_CHECKSUM = '3d6b9f06410d179a7f7404d4bf4c3c70';
|
||||
const PACKAGE_VERSION = '2.7.0';
|
||||
const INTEGRITY_CHECKSUM = '00729d72e3b82faf54ca8b9621dbb96f';
|
||||
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse');
|
||||
const activeClientIds = new Set();
|
||||
|
||||
self.addEventListener('install', function () {
|
||||
@@ -47,7 +49,10 @@ self.addEventListener('message', async function (event) {
|
||||
case 'INTEGRITY_CHECK_REQUEST': {
|
||||
sendToClient(client, {
|
||||
type: 'INTEGRITY_CHECK_RESPONSE',
|
||||
payload: INTEGRITY_CHECKSUM,
|
||||
payload: {
|
||||
packageVersion: PACKAGE_VERSION,
|
||||
checksum: INTEGRITY_CHECKSUM,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -57,7 +62,12 @@ self.addEventListener('message', async function (event) {
|
||||
|
||||
sendToClient(client, {
|
||||
type: 'MOCKING_ENABLED',
|
||||
payload: true,
|
||||
payload: {
|
||||
client: {
|
||||
id: client.id,
|
||||
frameType: client.frameType,
|
||||
},
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -86,12 +96,6 @@ self.addEventListener('message', async function (event) {
|
||||
|
||||
self.addEventListener('fetch', function (event) {
|
||||
const { request } = event;
|
||||
const accept = request.headers.get('accept') || '';
|
||||
|
||||
// Bypass server-sent events.
|
||||
if (accept.includes('text/event-stream')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bypass navigation requests.
|
||||
if (request.mode === 'navigate') {
|
||||
@@ -112,29 +116,8 @@ self.addEventListener('fetch', function (event) {
|
||||
}
|
||||
|
||||
// Generate unique request ID.
|
||||
const requestId = Math.random().toString(16).slice(2);
|
||||
|
||||
event.respondWith(
|
||||
handleRequest(event, requestId).catch((error) => {
|
||||
if (error.name === 'NetworkError') {
|
||||
console.warn(
|
||||
'[MSW] Successfully emulated a network error for the "%s %s" request.',
|
||||
request.method,
|
||||
request.url
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// At this point, any exception indicates an issue with the original request/response.
|
||||
console.error(
|
||||
`\
|
||||
[MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`,
|
||||
request.method,
|
||||
request.url,
|
||||
`${error.name}: ${error.message}`
|
||||
);
|
||||
})
|
||||
);
|
||||
const requestId = crypto.randomUUID();
|
||||
event.respondWith(handleRequest(event, requestId));
|
||||
});
|
||||
|
||||
async function handleRequest(event, requestId) {
|
||||
@@ -146,20 +129,24 @@ async function handleRequest(event, requestId) {
|
||||
// this message will pend indefinitely.
|
||||
if (client && activeClientIds.has(client.id)) {
|
||||
(async function () {
|
||||
const clonedResponse = response.clone();
|
||||
sendToClient(client, {
|
||||
type: 'RESPONSE',
|
||||
payload: {
|
||||
requestId,
|
||||
type: clonedResponse.type,
|
||||
ok: clonedResponse.ok,
|
||||
status: clonedResponse.status,
|
||||
statusText: clonedResponse.statusText,
|
||||
body: clonedResponse.body === null ? null : await clonedResponse.text(),
|
||||
headers: Object.fromEntries(clonedResponse.headers.entries()),
|
||||
redirected: clonedResponse.redirected,
|
||||
const responseClone = response.clone();
|
||||
|
||||
sendToClient(
|
||||
client,
|
||||
{
|
||||
type: 'RESPONSE',
|
||||
payload: {
|
||||
requestId,
|
||||
isMockedResponse: IS_MOCKED_RESPONSE in response,
|
||||
type: responseClone.type,
|
||||
status: responseClone.status,
|
||||
statusText: responseClone.statusText,
|
||||
body: responseClone.body,
|
||||
headers: Object.fromEntries(responseClone.headers.entries()),
|
||||
},
|
||||
},
|
||||
});
|
||||
[responseClone.body]
|
||||
);
|
||||
})();
|
||||
}
|
||||
|
||||
@@ -173,6 +160,10 @@ async function handleRequest(event, requestId) {
|
||||
async function resolveMainClient(event) {
|
||||
const client = await self.clients.get(event.clientId);
|
||||
|
||||
if (activeClientIds.has(event.clientId)) {
|
||||
return client;
|
||||
}
|
||||
|
||||
if (client?.frameType === 'top-level') {
|
||||
return client;
|
||||
}
|
||||
@@ -195,20 +186,32 @@ async function resolveMainClient(event) {
|
||||
|
||||
async function getResponse(event, client, requestId) {
|
||||
const { request } = event;
|
||||
const clonedRequest = request.clone();
|
||||
|
||||
// Clone the request because it might've been already used
|
||||
// (i.e. its body has been read and sent to the client).
|
||||
const requestClone = request.clone();
|
||||
|
||||
function passthrough() {
|
||||
// Clone the request because it might've been already used
|
||||
// (i.e. its body has been read and sent to the client).
|
||||
const headers = Object.fromEntries(clonedRequest.headers.entries());
|
||||
// Cast the request headers to a new Headers instance
|
||||
// so the headers can be manipulated with.
|
||||
const headers = new Headers(requestClone.headers);
|
||||
|
||||
// Remove MSW-specific request headers so the bypassed requests
|
||||
// comply with the server's CORS preflight check.
|
||||
// Operate with the headers as an object because request "Headers"
|
||||
// are immutable.
|
||||
delete headers['x-msw-bypass'];
|
||||
// Remove the "accept" header value that marked this request as passthrough.
|
||||
// This prevents request alteration and also keeps it compliant with the
|
||||
// user-defined CORS policies.
|
||||
const acceptHeader = headers.get('accept');
|
||||
if (acceptHeader) {
|
||||
const values = acceptHeader.split(',').map((value) => value.trim());
|
||||
const filteredValues = values.filter((value) => value !== 'msw/passthrough');
|
||||
|
||||
return fetch(clonedRequest, { headers });
|
||||
if (filteredValues.length > 0) {
|
||||
headers.set('accept', filteredValues.join(', '));
|
||||
} else {
|
||||
headers.delete('accept');
|
||||
}
|
||||
}
|
||||
|
||||
return fetch(requestClone, { headers });
|
||||
}
|
||||
|
||||
// Bypass mocking when the client is not active.
|
||||
@@ -224,57 +227,46 @@ async function getResponse(event, client, requestId) {
|
||||
return passthrough();
|
||||
}
|
||||
|
||||
// Bypass requests with the explicit bypass header.
|
||||
// Such requests can be issued by "ctx.fetch()".
|
||||
if (request.headers.get('x-msw-bypass') === 'true') {
|
||||
return passthrough();
|
||||
}
|
||||
|
||||
// Notify the client that a request has been intercepted.
|
||||
const clientMessage = await sendToClient(client, {
|
||||
type: 'REQUEST',
|
||||
payload: {
|
||||
id: requestId,
|
||||
url: request.url,
|
||||
method: request.method,
|
||||
headers: Object.fromEntries(request.headers.entries()),
|
||||
cache: request.cache,
|
||||
mode: request.mode,
|
||||
credentials: request.credentials,
|
||||
destination: request.destination,
|
||||
integrity: request.integrity,
|
||||
redirect: request.redirect,
|
||||
referrer: request.referrer,
|
||||
referrerPolicy: request.referrerPolicy,
|
||||
body: await request.text(),
|
||||
bodyUsed: request.bodyUsed,
|
||||
keepalive: request.keepalive,
|
||||
const requestBuffer = await request.arrayBuffer();
|
||||
const clientMessage = await sendToClient(
|
||||
client,
|
||||
{
|
||||
type: 'REQUEST',
|
||||
payload: {
|
||||
id: requestId,
|
||||
url: request.url,
|
||||
mode: request.mode,
|
||||
method: request.method,
|
||||
headers: Object.fromEntries(request.headers.entries()),
|
||||
cache: request.cache,
|
||||
credentials: request.credentials,
|
||||
destination: request.destination,
|
||||
integrity: request.integrity,
|
||||
redirect: request.redirect,
|
||||
referrer: request.referrer,
|
||||
referrerPolicy: request.referrerPolicy,
|
||||
body: requestBuffer,
|
||||
keepalive: request.keepalive,
|
||||
},
|
||||
},
|
||||
});
|
||||
[requestBuffer]
|
||||
);
|
||||
|
||||
switch (clientMessage.type) {
|
||||
case 'MOCK_RESPONSE': {
|
||||
return respondWithMock(clientMessage.data);
|
||||
}
|
||||
|
||||
case 'MOCK_NOT_FOUND': {
|
||||
case 'PASSTHROUGH': {
|
||||
return passthrough();
|
||||
}
|
||||
|
||||
case 'NETWORK_ERROR': {
|
||||
const { name, message } = clientMessage.data;
|
||||
const networkError = new Error(message);
|
||||
networkError.name = name;
|
||||
|
||||
// Rejecting a "respondWith" promise emulates a network error.
|
||||
throw networkError;
|
||||
}
|
||||
}
|
||||
|
||||
return passthrough();
|
||||
}
|
||||
|
||||
function sendToClient(client, message) {
|
||||
function sendToClient(client, message, transferrables = []) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const channel = new MessageChannel();
|
||||
|
||||
@@ -286,17 +278,25 @@ function sendToClient(client, message) {
|
||||
resolve(event.data);
|
||||
};
|
||||
|
||||
client.postMessage(message, [channel.port2]);
|
||||
});
|
||||
}
|
||||
|
||||
function sleep(timeMs) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, timeMs);
|
||||
client.postMessage(message, [channel.port2].concat(transferrables.filter(Boolean)));
|
||||
});
|
||||
}
|
||||
|
||||
async function respondWithMock(response) {
|
||||
await sleep(response.delay);
|
||||
return new Response(response.body, response);
|
||||
// Setting response status code to 0 is a no-op.
|
||||
// However, when responding with a "Response.error()", the produced Response
|
||||
// instance will have status code set to 0. Since it's not possible to create
|
||||
// a Response instance with status code 0, handle that use-case separately.
|
||||
if (response.status === 0) {
|
||||
return Response.error();
|
||||
}
|
||||
|
||||
const mockedResponse = new Response(response.body, response);
|
||||
|
||||
Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, {
|
||||
value: true,
|
||||
enumerable: true,
|
||||
});
|
||||
|
||||
return mockedResponse;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export const ApplicationStoryBook: any = () => (
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
export const ApplicationjQuery: any = () => (
|
||||
export const ApplicationJquery: any = () => (
|
||||
<MemoryRouter initialEntries={[`/-/web/detail/jquery`]}>
|
||||
<AppRoute />
|
||||
</MemoryRouter>
|
||||
|
||||
@@ -35,7 +35,7 @@ export const AuthorAll: any = () => (
|
||||
/>
|
||||
);
|
||||
|
||||
export const NoDAuthor: any = () => (
|
||||
export const NoAuthor: any = () => (
|
||||
<Author
|
||||
packageMeta={{
|
||||
latest: {
|
||||
|
||||
@@ -6,6 +6,21 @@ export default {
|
||||
title: 'Components/Sidebar/Engines',
|
||||
};
|
||||
|
||||
export const EnginesAll: any = () => (
|
||||
<Engines
|
||||
packageMeta={{
|
||||
latest: {
|
||||
engines: {
|
||||
node: '>= 18',
|
||||
pnpm: '>7',
|
||||
yarn: '>3',
|
||||
npm: '>3',
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
export const EnginesNpmNode: any = () => (
|
||||
<Engines
|
||||
packageMeta={{
|
||||
@@ -54,18 +69,3 @@ export const EnginesPnpm: any = () => (
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
export const EnginesAll: any = () => (
|
||||
<Engines
|
||||
packageMeta={{
|
||||
latest: {
|
||||
engines: {
|
||||
node: '>= 18',
|
||||
pnpm: '>7',
|
||||
yarn: '>3',
|
||||
npm: '>3',
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -40,7 +40,7 @@ const Help: React.FC = () => {
|
||||
t('help.second-step'),
|
||||
t('help.second-step-command-line', { registryUrl })
|
||||
)}
|
||||
<Typography variant="body2">{t('help.third-step')}</Typography>
|
||||
<Typography variant="body1">{t('help.third-step')}</Typography>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button color="primary" href="https://verdaccio.org/docs/cli-registry" size="small">
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
import { vi } from 'vitest';
|
||||
|
||||
// import { generateTokenWithTimeRange } from '../../../jest/unit/components/__mocks__/token';
|
||||
import { generateTokenWithTimeRange } from '../../utils/token-generate';
|
||||
|
||||
describe('getDefaultUserState', (): void => {
|
||||
const username = 'xyz';
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
test('should return state with empty user', async () => {
|
||||
const token = 'token-xx-xx-xx';
|
||||
vi.doMock('../storage', async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import('../storage')>()),
|
||||
getItem: (key: string) => (key === 'token' ? token : username),
|
||||
|
||||
vi.doMock('../storage', () => ({
|
||||
default: {
|
||||
getItem: (key: string) => (key === 'token' ? token : username),
|
||||
},
|
||||
}));
|
||||
|
||||
const Login = await import('./login');
|
||||
const { getDefaultUserState } = Login;
|
||||
const result = {
|
||||
@@ -24,19 +28,21 @@ describe('getDefaultUserState', (): void => {
|
||||
expect(getDefaultUserState()).toEqual(result);
|
||||
});
|
||||
|
||||
// test('should return state with user from storage', async () => {
|
||||
// const token = generateTokenWithTimeRange(24);
|
||||
//
|
||||
// vi.doMock('../storage', async (importOriginal) => ({
|
||||
// ...(await importOriginal<typeof import('../storage')>()),
|
||||
// getItem: (key: string) => (key === 'token' ? token : username),
|
||||
// }));
|
||||
// const Login = await import('./login');
|
||||
// const { getDefaultUserState } = Login;
|
||||
// const result = {
|
||||
// token,
|
||||
// username,
|
||||
// };
|
||||
// expect(getDefaultUserState()).toEqual(result);
|
||||
// });
|
||||
test('should return state with user from storage', async () => {
|
||||
const token = generateTokenWithTimeRange(24);
|
||||
|
||||
vi.doMock('../storage', () => ({
|
||||
default: {
|
||||
getItem: (key: string) => (key === 'token' ? token : username),
|
||||
},
|
||||
}));
|
||||
|
||||
const Login = await import('./login');
|
||||
const { getDefaultUserState } = Login;
|
||||
const result = {
|
||||
token,
|
||||
username,
|
||||
};
|
||||
expect(getDefaultUserState()).toEqual(result);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { vi } from 'vitest';
|
||||
|
||||
/* eslint-disable jest/no-mocks-import */
|
||||
import { isTokenExpire } from './token';
|
||||
import {
|
||||
generateInvalidToken,
|
||||
generateTokenWithExpirationAsString,
|
||||
generateTokenWithOutExpiration,
|
||||
generateTokenWithTimeRange,
|
||||
} from '../../vitest/unit/components/__mocks__/token';
|
||||
import { isTokenExpire } from './token';
|
||||
} from './token-generate';
|
||||
|
||||
/* eslint-disable no-console */
|
||||
console.error = vi.fn();
|
||||
|
||||
@@ -22,6 +22,7 @@ export default defineConfig({
|
||||
'\\.(jpg)$': './vitest/unit/empty.ts',
|
||||
'\\.(md)$': './vitest/unit/empty-string.ts',
|
||||
},
|
||||
testTimeout: 15000,
|
||||
},
|
||||
plugins: [
|
||||
react({
|
||||
|
||||
@@ -1,82 +1,74 @@
|
||||
import fs from 'fs';
|
||||
import { rest } from 'msw';
|
||||
|
||||
const packagesPayload = require('./api/home-packages.json');
|
||||
import { HttpResponse, http } from 'msw';
|
||||
import path from 'path';
|
||||
|
||||
export const handlers = [
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/packages', (req, res, ctx) => {
|
||||
return res(ctx.json(Array(400).fill(packagesPayload)));
|
||||
http.get('http://localhost:9000/-/verdaccio/data/packages', () => {
|
||||
return HttpResponse.json(Array(400).fill(require('./api/home-packages.json')));
|
||||
}),
|
||||
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/sidebar/storybook', (req, res, ctx) => {
|
||||
const { v } = req.params;
|
||||
http.get('http://localhost:9000/-/verdaccio/data/sidebar/storybook', ({ params }) => {
|
||||
const { v } = params;
|
||||
if (v) {
|
||||
return res(ctx.json(require('./api/storybook-v.json')));
|
||||
return HttpResponse.json(require('./api/storybook-v.json'));
|
||||
} else {
|
||||
return res(ctx.json(require('./api/storybook-sidebar.json')));
|
||||
return HttpResponse.json(require('./api/storybook-sidebar.json'));
|
||||
}
|
||||
}),
|
||||
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/search/*', (req, res, ctx) => {
|
||||
return res(ctx.json(require('./api/search-verdaccio.json')));
|
||||
http.get('http://localhost:9000/-/verdaccio/data/search/*', () => {
|
||||
return HttpResponse.json(require('./api/search-verdaccio.json'));
|
||||
}),
|
||||
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/package/readme/storybook', (req, res, ctx) => {
|
||||
return res(ctx.text(require('./api/storybook-readme')()));
|
||||
http.get('http://localhost:9000/-/verdaccio/data/package/readme/storybook', () => {
|
||||
return HttpResponse.text(require('./api/storybook-readme')());
|
||||
}),
|
||||
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/sidebar/jquery', (req, res, ctx) => {
|
||||
return res(ctx.json(require('./api/jquery-sidebar.json')));
|
||||
http.get('http://localhost:9000/-/verdaccio/data/sidebar/jquery', () => {
|
||||
return HttpResponse.json(require('./api/jquery-sidebar.json'));
|
||||
}),
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/sidebar/JSONStream', (req, res, ctx) => {
|
||||
return res(ctx.status(401)); // unauthorized
|
||||
http.get('http://localhost:9000/-/verdaccio/data/sidebar/JSONStream', () => {
|
||||
return new HttpResponse('unauthorized', { status: 401 });
|
||||
}),
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/sidebar/semver', (req, res, ctx) => {
|
||||
return res(ctx.status(500)); // internal server error
|
||||
http.get('http://localhost:9000/-/verdaccio/data/sidebar/semver', () => {
|
||||
return new HttpResponse('internal server error', { status: 500 });
|
||||
}),
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/sidebar/kleur', (req, res, ctx) => {
|
||||
return res(ctx.status(404)); // not found
|
||||
http.get('http://localhost:9000/-/verdaccio/data/sidebar/kleur', () => {
|
||||
return new HttpResponse('not found', { status: 404 });
|
||||
}),
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/sidebar/glob', (req, res, ctx) => {
|
||||
return res(ctx.json(require('./api/glob-sidebar.json')));
|
||||
http.get('http://localhost:9000/-/verdaccio/data/sidebar/glob', () => {
|
||||
return HttpResponse.json(require('./api/glob-sidebar.json'));
|
||||
}),
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/package/readme/glob', (req, res, ctx) => {
|
||||
return res(ctx.text('foo glob'));
|
||||
http.get('http://localhost:9000/-/verdaccio/data/package/readme/glob', () => {
|
||||
return HttpResponse.text('foo glob');
|
||||
}),
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/sidebar/got', (req, res, ctx) => {
|
||||
return res(ctx.json(require('./api/got-sidebar.json')));
|
||||
http.get('http://localhost:9000/-/verdaccio/data/sidebar/got', () => {
|
||||
return HttpResponse.json(require('./api/got-sidebar.json'));
|
||||
}),
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/package/readme/got', (req, res, ctx) => {
|
||||
return res(ctx.text('foo got'));
|
||||
http.get('http://localhost:9000/-/verdaccio/data/package/readme/got', () => {
|
||||
return HttpResponse.text('foo got');
|
||||
}),
|
||||
rest.get('http://localhost:9000/-/verdaccio/data/package/readme/jquery', (req, res, ctx) => {
|
||||
return res(ctx.text(require('./api/jquery-readme')()));
|
||||
http.get('http://localhost:9000/-/verdaccio/data/package/readme/jquery', () => {
|
||||
return HttpResponse.text(require('./api/jquery-readme')());
|
||||
}),
|
||||
rest.get('http://localhost:9000/verdaccio/-/verdaccio-1.0.0.tgz', (req, res, ctx) => {
|
||||
const fileContent = fs.readFileSync('./api/verdaccio-1.0.0.tgz');
|
||||
return res(
|
||||
ctx.status(200),
|
||||
ctx.set('Content-Type', 'application/octet-stream'),
|
||||
ctx.body(fileContent)
|
||||
);
|
||||
http.get('http://localhost:9000/verdaccio/-/verdaccio-1.0.0.tgz', () => {
|
||||
const fileName = path.resolve(__dirname, './api/verdaccio-1.0.0.tgz');
|
||||
const fileContent = fs.readFileSync(fileName);
|
||||
return new HttpResponse(fileContent, {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/octet-stream' },
|
||||
});
|
||||
}),
|
||||
|
||||
rest.post<{ username: string; password: string }, { token: string; username: string }>(
|
||||
http.post<{ username: string; password: string }, { token: string; username: string }>(
|
||||
'http://localhost:9000/-/verdaccio/sec/login',
|
||||
// @ts-ignore
|
||||
async (req, res, ctx) => {
|
||||
// @ts-ignore
|
||||
const body = await req.json();
|
||||
async ({ request }) => {
|
||||
const body = await request.json();
|
||||
if (body.username === 'fail') {
|
||||
return ctx.status(401);
|
||||
return new HttpResponse('unauthorized', { status: 401 });
|
||||
}
|
||||
|
||||
return res(
|
||||
ctx.json({
|
||||
username: body.username,
|
||||
token: 'valid token',
|
||||
})
|
||||
);
|
||||
return HttpResponse.json({ username: body.username, token: 'valid token' });
|
||||
}
|
||||
),
|
||||
];
|
||||
|
||||
5763
pnpm-lock.yaml
generated
5763
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user