From 86afd63530f94519d95ed34a5aa5c4ad9f083e93 Mon Sep 17 00:00:00 2001 From: Stephanie Zeng Date: Fri, 26 Apr 2024 14:52:55 -0400 Subject: [PATCH 1/2] feat: add workflow to deploy storybook to github page --- .github/workflows/deploy-storybook.yml | 56 ++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 .github/workflows/deploy-storybook.yml diff --git a/.github/workflows/deploy-storybook.yml b/.github/workflows/deploy-storybook.yml new file mode 100644 index 0000000..d0f484a --- /dev/null +++ b/.github/workflows/deploy-storybook.yml @@ -0,0 +1,56 @@ +name: Deploy Storybook to Github Page for PR + +on: + pull_request: + branches: ['main'] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + main: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x] + steps: + - name: Checkout the codebase + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + + - name: Install Dependencies + run: npm ci + + - name: Init MSW + run: npx msw init public/ + + - name: Build Storybook + run: npm run build-storybook + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./storybook-static + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 From fca3881d5e8751d13fced7baf5b30b89c86a1873 Mon Sep 17 00:00:00 2001 From: Stephanie Zeng Date: Fri, 26 Apr 2024 15:29:52 -0400 Subject: [PATCH 2/2] fix: remove msw --- .github/workflows/deploy-storybook.yml | 3 - .storybook/preview.ts | 6 - package.json | 5 - pages/index.stories.tsx | 79 ------- public/mockServiceWorker.js | 303 ------------------------- 5 files changed, 396 deletions(-) delete mode 100644 pages/index.stories.tsx delete mode 100644 public/mockServiceWorker.js diff --git a/.github/workflows/deploy-storybook.yml b/.github/workflows/deploy-storybook.yml index d0f484a..f6a2d6d 100644 --- a/.github/workflows/deploy-storybook.yml +++ b/.github/workflows/deploy-storybook.yml @@ -37,9 +37,6 @@ jobs: - name: Install Dependencies run: npm ci - - name: Init MSW - run: npx msw init public/ - - name: Build Storybook run: npm run build-storybook diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 3cd9550..438298f 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,11 +1,6 @@ import type { Preview } from "@storybook/react"; import '../styles/globals.css'; // replace with the name of your tailwind css file -import { initialize, mswLoader } from 'msw-storybook-addon'; - -// Initialize MSW -initialize(); - const preview: Preview = { parameters: { actions: { argTypesRegex: "^on[A-Z].*" }, @@ -16,7 +11,6 @@ const preview: Preview = { }, }, }, - loaders: [mswLoader], }; export default preview; diff --git a/package.json b/package.json index 2b3f70a..65f5dc5 100644 --- a/package.json +++ b/package.json @@ -45,15 +45,10 @@ "eslint": "^8", "eslint-config-next": "13.5.4", "eslint-plugin-storybook": "^0.6.15", - "msw": "^1.3.2", - "msw-storybook-addon": "^1.10.0", "plop": "^4.0.0", "postcss": "^8", "storybook": "^8.0.0-beta.1", "tailwindcss": "^3", "typescript": "^5" - }, - "msw": { - "workerDirectory": "public" } } diff --git a/pages/index.stories.tsx b/pages/index.stories.tsx deleted file mode 100644 index e6d5194..0000000 --- a/pages/index.stories.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from "react"; -import { StoryObj, Meta } from "@storybook/react"; -import { rest } from 'msw' -import Index from "./index"; - -export default { - title: "Page/Home", - component: Index, -}; - -export const Success = { - parameters: { - msw: { - handlers: [ - rest.get('http://localhost:3000/api/profiles', (req, res, ctx) => { - return res( - ctx.json([ - { - id: "1", - fullName: "DR. MSW", - location: "3 miles away", - description: "I'm a part-time dog walker in the North York area. Let me know if you need someone to walk your dog!", - }]) - ) - }), - ] - }, - }, -}; - -export const Loading = { - parameters: { - msw: { - handlers: [ - rest.get('http://localhost:3000/api/profiles', (req, res, ctx) => { - return res( - ctx.delay(1000*3), - ctx.json([ - { - id: "1", - fullName: "DR. MSW", - location: "3 miles away", - description: "I'm a part-time dog walker in the North York area. Let me know if you need someone to walk your dog!", - }]) - ) - }), - ] - }, - }, -}; - -export const Empty = { - parameters: { - msw: { - handlers: [ - rest.get('http://localhost:3000/api/profiles', (req, res, ctx) => { - return res( - ctx.json([]) - ) - }), - ] - }, - }, -}; - -export const Error = { - parameters: { - msw: { - handlers: [ - rest.get('http://localhost:3000/api/profiles', (req, res, ctx) => { - return res( - ctx.status(500) - ) - }), - ] - }, - }, -} - diff --git a/public/mockServiceWorker.js b/public/mockServiceWorker.js deleted file mode 100644 index 51d85ee..0000000 --- a/public/mockServiceWorker.js +++ /dev/null @@ -1,303 +0,0 @@ -/* eslint-disable */ -/* tslint:disable */ - -/** - * Mock Service Worker (1.3.2). - * @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 activeClientIds = new Set() - -self.addEventListener('install', function () { - self.skipWaiting() -}) - -self.addEventListener('activate', function (event) { - event.waitUntil(self.clients.claim()) -}) - -self.addEventListener('message', async function (event) { - const clientId = event.source.id - - if (!clientId || !self.clients) { - return - } - - const client = await self.clients.get(clientId) - - if (!client) { - return - } - - const allClients = await self.clients.matchAll({ - type: 'window', - }) - - switch (event.data) { - case 'KEEPALIVE_REQUEST': { - sendToClient(client, { - type: 'KEEPALIVE_RESPONSE', - }) - break - } - - case 'INTEGRITY_CHECK_REQUEST': { - sendToClient(client, { - type: 'INTEGRITY_CHECK_RESPONSE', - payload: INTEGRITY_CHECKSUM, - }) - break - } - - case 'MOCK_ACTIVATE': { - activeClientIds.add(clientId) - - sendToClient(client, { - type: 'MOCKING_ENABLED', - payload: true, - }) - break - } - - case 'MOCK_DEACTIVATE': { - activeClientIds.delete(clientId) - break - } - - case 'CLIENT_CLOSED': { - activeClientIds.delete(clientId) - - const remainingClients = allClients.filter((client) => { - return client.id !== clientId - }) - - // Unregister itself when there are no more clients - if (remainingClients.length === 0) { - self.registration.unregister() - } - - break - } - } -}) - -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') { - return - } - - // Opening the DevTools triggers the "only-if-cached" request - // that cannot be handled by the worker. Bypass such requests. - if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { - return - } - - // Bypass all requests when there are no active clients. - // Prevents the self-unregistered worked from handling requests - // after it's been deleted (still remains active until the next reload). - if (activeClientIds.size === 0) { - return - } - - // 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}`, - ) - }), - ) -}) - -async function handleRequest(event, requestId) { - const client = await resolveMainClient(event) - const response = await getResponse(event, client, requestId) - - // Send back the response clone for the "response:*" life-cycle events. - // Ensure MSW is active and ready to handle the message, otherwise - // 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, - }, - }) - })() - } - - return response -} - -// Resolve the main client for the given event. -// Client that issues a request doesn't necessarily equal the client -// that registered the worker. It's with the latter the worker should -// communicate with during the response resolving phase. -async function resolveMainClient(event) { - const client = await self.clients.get(event.clientId) - - if (client?.frameType === 'top-level') { - return client - } - - const allClients = await self.clients.matchAll({ - type: 'window', - }) - - return allClients - .filter((client) => { - // Get only those clients that are currently visible. - return client.visibilityState === 'visible' - }) - .find((client) => { - // Find the client ID that's recorded in the - // set of clients that have registered the worker. - return activeClientIds.has(client.id) - }) -} - -async function getResponse(event, client, requestId) { - const { request } = event - const clonedRequest = 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()) - - // 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'] - - return fetch(clonedRequest, { headers }) - } - - // Bypass mocking when the client is not active. - if (!client) { - return passthrough() - } - - // Bypass initial page load requests (i.e. static assets). - // The absence of the immediate/parent client in the map of the active clients - // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet - // and is not ready to handle requests. - if (!activeClientIds.has(client.id)) { - 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, - }, - }) - - switch (clientMessage.type) { - case 'MOCK_RESPONSE': { - return respondWithMock(clientMessage.data) - } - - case 'MOCK_NOT_FOUND': { - 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) { - return new Promise((resolve, reject) => { - const channel = new MessageChannel() - - channel.port1.onmessage = (event) => { - if (event.data && event.data.error) { - return reject(event.data.error) - } - - resolve(event.data) - } - - client.postMessage(message, [channel.port2]) - }) -} - -function sleep(timeMs) { - return new Promise((resolve) => { - setTimeout(resolve, timeMs) - }) -} - -async function respondWithMock(response) { - await sleep(response.delay) - return new Response(response.body, response) -}