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)
);