Skip to content
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
11 changes: 7 additions & 4 deletions e2e/daily.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import AxeBuilder from '@axe-core/playwright';
import { expect, test } from '@playwright/test';
import { waitForHydrated } from './fixtures/hydration';

import { completeLocalOnboarding } from './fixtures/local-onboarding';

Expand Down Expand Up @@ -28,8 +29,9 @@ test.describe('Journal, list & manifesto', () => {
test('list completion and weekly writing persist independently', async ({ page }) => {
await completeLocalOnboarding(page);
await page.goto('/bucket-list');
await page.getByLabel('Something you want to do').fill('Walk after lunch');
await page.getByRole('button', { name: 'Add to my list' }).click();
await waitForHydrated(page.getByLabel('I want to…'));
await page.getByLabel('I want to…').fill('Walk after lunch');
await page.getByRole('button', { name: 'Add my wording', exact: true }).click();
await page.getByRole('button', { name: 'Complete Walk after lunch', exact: true }).click();

await page.goto('/journal');
Expand Down Expand Up @@ -68,6 +70,7 @@ test.describe('Journal, list & manifesto', () => {

test('a catalog idea can be saved and completed with no setup', async ({ page }) => {
await page.goto('/experiences');
await waitForHydrated(page.getByLabel('Search everything'));
await page.getByLabel('Search everything').fill('Make pasta from scratch');
await page
.getByRole('button', { name: 'Add Make pasta from scratch to my bucket list', exact: true })
Expand Down Expand Up @@ -163,15 +166,15 @@ test.describe('Journal, list & manifesto', () => {
await page.getByRole('button', { name: 'Open menu' }).click();
}
const nav = page.locator('[data-site-nav]');
for (const name of ['Catalog', 'My list', 'Weekly journal', 'Life in weeks']) {
for (const name of ['Explore', 'My list', 'Weekly journal', 'Life in weeks']) {
await expect(nav.getByRole('link', { name, exact: true })).toBeVisible();
}
});

test('public footer leads to catalog and local workspaces', async ({ page }) => {
await page.goto('/hobbies');
const footer = page.locator('[data-site-footer]');
await expect(footer.getByRole('link', { name: 'Catalog', exact: true })).toBeVisible();
await expect(footer.getByRole('link', { name: 'Explore', exact: true })).toBeVisible();
await expect(footer.getByRole('link', { name: 'My list', exact: true })).toBeVisible();
await expect(footer.getByRole('link', { name: 'Weekly journal', exact: true })).toBeVisible();
await expect(footer.getByRole('link', { name: 'Habits', exact: true })).toHaveCount(0);
Expand Down
4 changes: 3 additions & 1 deletion e2e/experiences.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ test.describe('Manual bucket-list entry', () => {
}) => {
await page.goto('/bucket-list');
await waitForHydrated(page.getByLabel('I want to…'));
await page.getByLabel('I want to…').pressSequentially('pot');
await expect(page.getByLabel('I want to…')).toBeEnabled();
await page.getByLabel('I want to…').pressSequentially('pot', { delay: 50 });
await expect(page.getByLabel('I want to…')).toHaveValue('pot');
await expect(
page.getByRole('button', {
name: 'Add Take a pottery class and make a finished piece to my list',
Expand Down
23 changes: 13 additions & 10 deletions e2e/guest-access.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect, test } from '@playwright/test';
import { waitForHydrated } from './fixtures/hydration';

import { completeLocalOnboarding } from './fixtures/local-onboarding';

Expand All @@ -14,10 +15,10 @@ test.describe('private work is locally available without an account', () => {
test('core navigation is available without onboarding', async ({ page }) => {
await page.goto('/experiences');
const nav = page.locator('[data-site-nav]');
if (!(await nav.getByRole('link', { name: 'Catalog', exact: true }).isVisible())) {
if (!(await nav.getByRole('link', { name: 'Explore', exact: true }).isVisible())) {
await page.getByRole('button', { name: 'Open menu' }).click();
}
for (const name of ['Catalog', 'My list', 'Weekly journal', 'Life in weeks']) {
for (const name of ['Explore', 'My list', 'Weekly journal', 'Life in weeks']) {
await expect(nav.getByRole('link', { name, exact: true })).toBeVisible();
}
await expect(nav.getByRole('link', { name: 'Habits', exact: true })).toHaveCount(0);
Expand All @@ -43,11 +44,12 @@ test.describe('private work is locally available without an account', () => {
test('bucket list is a complete local workspace without onboarding', async ({ page }) => {
await page.goto('/bucket-list');
await expect(page).toHaveURL(/\/bucket-list$/);
await page.getByLabel('Something you want to do').fill('Sleep under the stars');
await page.getByRole('button', { name: 'Add to my list' }).click();
await expect(page.getByText('Sleep under the stars')).toBeVisible();
await waitForHydrated(page.getByLabel('I want to…'));
await page.getByLabel('I want to…').fill('Sleep under the stars');
await page.getByRole('button', { name: 'Add my wording', exact: true }).click();
await expect(page.getByText('Sleep under the stars', { exact: true })).toBeVisible();
await page.reload();
await expect(page.getByText('Sleep under the stars')).toBeVisible();
await expect(page.getByText('Sleep under the stars', { exact: true })).toBeVisible();
await page.getByRole('button', { name: 'Complete Sleep under the stars' }).click();
await expect(page.getByRole('button', { name: 'Reopen Sleep under the stars' })).toBeVisible();
});
Expand All @@ -58,9 +60,10 @@ test('bucket draft survives a transaction abort and retries without losing saved
}) => {
await completeLocalOnboarding(page);
await page.goto('/bucket-list');
const input = page.getByLabel('Something you want to do');
const input = page.getByLabel('I want to…');
await waitForHydrated(input);
await input.fill('Watch a sunrise');
await page.getByRole('button', { name: 'Add to my list' }).click();
await page.getByRole('button', { name: 'Add my wording', exact: true }).click();
await expect(page.getByRole('button', { name: 'Complete Watch a sunrise' })).toBeVisible();

await page.evaluate(() => {
Expand All @@ -73,13 +76,13 @@ test('bucket draft survives a transaction abort and retries without losing saved
};
});
await input.fill('Sleep under the stars');
await page.getByRole('button', { name: 'Add to my list' }).click();
await page.getByRole('button', { name: 'Add my wording', exact: true }).click();
await expect(
page.getByRole('alert').filter({ hasText: 'Changes could not be saved' })
).toBeVisible();
await expect(input).toHaveValue('Sleep under the stars');
await expect(page.getByRole('button', { name: 'Complete Sleep under the stars' })).toHaveCount(0);
await page.getByRole('button', { name: 'Add to my list' }).click();
await page.getByRole('button', { name: 'Add my wording', exact: true }).click();
await expect(input).toHaveValue('');
await page.reload();
await expect(page.getByRole('button', { name: 'Complete Sleep under the stars' })).toBeVisible();
Expand Down
2 changes: 1 addition & 1 deletion e2e/life-atlas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test.describe('Life Atlas shell', () => {
if ((page.viewportSize()?.width ?? 0) < 1024) {
await page.getByRole('button', { name: 'Open menu' }).click();
}
await expect(nav.getByRole('link', { name: 'Catalog', exact: true })).toHaveAttribute(
await expect(nav.getByRole('link', { name: 'Explore', exact: true })).toHaveAttribute(
'href',
'/experiences'
);
Expand Down
2 changes: 1 addition & 1 deletion e2e/onboarding.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import { expect, test } from '@playwright/test';
test('the former onboarding URL opens the list without a questionnaire', async ({ page }) => {
await page.goto('/onboarding');
await expect(page).toHaveURL(/\/bucket-list$/);
await expect(page.getByLabel('Something you want to do')).toBeVisible();
await expect(page.getByLabel('I want to…')).toBeVisible();
await expect(page.getByText('When were you born?')).toHaveCount(0);
});
18 changes: 14 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"lucide-react": "1.27.0",
"motion": "^12.42.2",
"nanoid": "5.1.9",
"next": "16.3.6",
"next": "16.3.8",
"next-themes": "0.4.6",
"posthog-js": "^1.407.3",
"react": "19.2.8",
Expand Down Expand Up @@ -92,7 +92,7 @@
"jsdom": "29.1.1",
"knip": "^6.29.0",
"shadcn": "4.15.0",
"sharp": "^0.35.4",
"sharp": "^0.35.5",
"tailwindcss": "^4.3.3",
"tsx": "4.23.1",
"tw-animate-css": "1.4.0",
Expand All @@ -112,10 +112,20 @@
"nanoid@<3.3.18": ">=3.3.18",
"nanoid@>=4.0.0 <5.1.16": ">=5.1.16",
"mysql2@<3.22.0": ">=3.22.0",
"miniflare>sharp": "0.35.4",
"miniflare>sharp": "0.35.5",
"cosmiconfig>js-yaml": "4.3.2",
"undici@>=7.0.0 <7.29.1": "7.29.1",
"devalue@<=5.9.2": "5.9.3"
"devalue@<=5.9.2": "5.9.3",
"proxy-addr@<2.0.8": "2.0.8",
"source-map-js@<1.2.2": "1.2.2",
"@modelcontextprotocol/sdk@<1.31.0": "1.31.0",
"hono@<4.12.25": "4.12.25",
"postcss@<8.5.18": "8.5.18",
"ip-address@<10.3.1": "10.3.1",
"http-cache-semantics@<4.3.0": "4.3.0"
},
"patchedDependencies": {
"[email protected]": "patches/[email protected]"
}
}
}
10 changes: 10 additions & 0 deletions patches/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
diff --git a/lib/parse.js b/lib/parse.js
index 3a6988e629f52aee6609dc5ec290a5e9ff47cecb..5241072a98e0cf10b9a9975a52372a59835a37cd 100644
--- a/lib/parse.js
+++ b/lib/parse.js
@@ -76,1 +76,5 @@ const parse = (input, options = {}) => {
while (index < length) {
+ // Bound AST depth before the recursive compile/expand walkers run.
+ if (stack.length > 128) {
+ throw new SyntaxError('Brace pattern nesting exceeds 128 levels');
+ }
Loading
Loading