diff --git a/docs/application-overview.md b/docs/application-overview.md index b51f279..4272cdf 100644 --- a/docs/application-overview.md +++ b/docs/application-overview.md @@ -90,7 +90,7 @@ $ pnpm start Open up https://localhost/, then restart the server, you will see a notification ask you to restart reload the offline content. -## Maintaining +## Managing Updates - Update dependencies weekly using dependencies updater. I recommend using Vscode extensions: [Vscode Ecosystem](https://marketplace.visualstudio.com/items?itemName=rifandani.vscode-ecosystem) (also maintained by myself) - When you update `@playwright/test`, don't forget to also download new browser binaries and their dependencies by running `pnpm test:install` diff --git a/e2e/auth.setup.ts b/e2e/auth.setup.ts index 09c2a0c..206003c 100644 --- a/e2e/auth.setup.ts +++ b/e2e/auth.setup.ts @@ -8,8 +8,8 @@ test('auth setup', async ({ page }) => { const passwordInput = page.getByRole('textbox', { name: /password/i }); const submitBtn = page.getByRole('button', { name: /login/i }); - await usernameInput.fill('kminchelle'); - await passwordInput.fill('0lelplR'); + await usernameInput.fill('emilys'); + await passwordInput.fill('emilyspass'); await submitBtn.click(); await page.waitForURL(''); diff --git a/e2e/login.spec.ts b/e2e/login.spec.ts index 2a094a1..6ec4043 100644 --- a/e2e/login.spec.ts +++ b/e2e/login.spec.ts @@ -1,11 +1,11 @@ import { expect, test } from '@playwright/test'; -const validUsername = 'kminchelle'; -const validPassword = '0lelplR'; +const validUsername = 'emilys'; +const validPassword = 'emilyspass'; const invalidUsername = 'km'; const invalidPassword = '0lelp'; -const errorUsername = '1kminchelle'; -const errorPassword = '10lelplR'; +const errorUsername = '1emilys'; +const errorPassword = '1emilyspass'; test.describe('authorized', () => { test('should redirect back to home page', async ({ page }) => { diff --git a/e2e/todo.spec.ts b/e2e/todo.spec.ts index c4f8bf6..f8f0d81 100644 --- a/e2e/todo.spec.ts +++ b/e2e/todo.spec.ts @@ -4,12 +4,12 @@ test.describe('authorized', () => { test('should have title, and link that navigate back to /todos', async ({ page, }) => { - await page.goto('/todos/28'); + await page.goto('/todos/47'); const title = page.getByRole('heading', { name: 'Todo Detail' }); const homeLink = page.getByRole('link', { name: 'Home' }); const todosLink = page.getByRole('link', { name: 'Todos' }); - const todoDetailLink = page.getByRole('link', { name: '28' }); + const todoDetailLink = page.getByRole('link', { name: '47' }); await expect(title).toBeVisible(); await expect(homeLink).toBeVisible(); @@ -20,7 +20,7 @@ test.describe('authorized', () => { await page.waitForURL('/todos'); await expect(title).not.toBeVisible(); - await page.goto('/todos/28'); + await page.goto('/todos/47'); await homeLink.click(); await page.waitForURL('/'); }); @@ -29,7 +29,7 @@ test.describe('authorized', () => { // test.fixme(`should show error UI on invalid todo id in URL`, async ({page}) => {}) test(`should be able to update user's own todo`, async ({ page }) => { - await page.goto('/todos/28'); + await page.goto('/todos/47'); const input = page.getByRole('textbox', { name: 'todo detail input' }); const updateBtn = page.getByRole('button', { name: /update/i }); @@ -67,7 +67,7 @@ test.describe('unauthorized', () => { test.use({ storageState: { cookies: [], origins: [] } }); test('should redirect back to /login', async ({ page }) => { - await page.goto('/todos/28'); + await page.goto('/todos/47'); const usernameInput = page.getByRole('textbox', { name: /username/i }); const passwordInput = page.getByRole('textbox', { name: /password/i }); diff --git a/src/app/devtools.tsx b/src/app/devtools.tsx new file mode 100644 index 0000000..dc6aa51 --- /dev/null +++ b/src/app/devtools.tsx @@ -0,0 +1,31 @@ +import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; +import React from 'react'; + +const ReactQueryDevtoolsProduction = React.lazy(() => + import('@tanstack/react-query-devtools/build/modern/production.js').then( + (d) => ({ + default: d.ReactQueryDevtools, + }), + ), +); + +export function Devtools() { + const [showDevtools, setShowDevtools] = React.useState(false); + + React.useEffect(() => { + window.toggleRqDevtools = () => setShowDevtools((prev) => !prev); + }, []); + + return ( + <> + {/* this will only be rendered in development */} + + + {showDevtools && ( + + + + )} + + ); +} diff --git a/src/app/entry.tsx b/src/app/entry.tsx index d42cf04..6980451 100644 --- a/src/app/entry.tsx +++ b/src/app/entry.tsx @@ -1,5 +1,5 @@ -import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { StrictMode } from 'react'; +import { Devtools } from './devtools'; import { AppI18nProvider } from './providers/i18n/provider'; import { AppQueryProvider } from './providers/query/provider'; import { AppRouterProvider } from './providers/router/provider'; @@ -18,11 +18,7 @@ export function Entry() { {/* PWA */} - {/* react query devtools */} - + diff --git a/src/index.d.ts b/src/index.d.ts index 456ce1e..8ce00ec 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -5,3 +5,12 @@ declare module 'react' { [key: `--${string}`]: string | number; } } + +declare global { + interface Window { + /** + * Toggle react query devtools in production + */ + toggleRqDevtools: () => void; + } +} diff --git a/src/modules/auth/components/login-form.tsx b/src/modules/auth/components/login-form.tsx index c5d92c2..ec6d4f4 100644 --- a/src/modules/auth/components/login-form.tsx +++ b/src/modules/auth/components/login-form.tsx @@ -103,7 +103,8 @@ export function LoginForm() { className="mt-8" isDisabled={fetcher.state === 'submitting' || !formState.isValid} > - {t(fetcher.state === 'submitting' ? 'loginLoading' : 'login')} (0lelplR) + {t(fetcher.state === 'submitting' ? 'loginLoading' : 'login')}{' '} + (emilyspass) );