From 3879a55a1a09ff40920a28a23ff12a0bc9167855 Mon Sep 17 00:00:00 2001 From: Alan Daniel Date: Fri, 28 Nov 2025 16:42:31 -0400 Subject: [PATCH 1/6] add og image to re:invent page (#40898) * add og to re:invent page * og * fix * fix * fix * url --- apps/www/data/aws-reinvent-2025.tsx | 2 ++ apps/www/pages/aws-reinvent-2025.tsx | 9 ++++++++- apps/www/public/images/og/re_invent.png | Bin 0 -> 26465 bytes 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 apps/www/public/images/og/re_invent.png diff --git a/apps/www/data/aws-reinvent-2025.tsx b/apps/www/data/aws-reinvent-2025.tsx index b1554c59f16..63b3cfe9764 100644 --- a/apps/www/data/aws-reinvent-2025.tsx +++ b/apps/www/data/aws-reinvent-2025.tsx @@ -4,6 +4,7 @@ import { Image } from 'ui' import dynamic from 'next/dynamic' import MainProducts from './MainProducts' import { PRODUCT_SHORTNAMES } from 'shared-data/products' +import { SITE_ORIGIN } from '~/lib/constants' const AuthVisual = dynamic(() => import('components/Products/AuthVisual')) const FunctionsVisual = dynamic(() => import('components/Products/FunctionsVisual')) @@ -53,6 +54,7 @@ const data = { metaTitle: 'Supabase at AWS re:Invent 2025 | December 1-4, Las Vegas', metaDescription: 'Meet Supabase at AWS re:Invent 2025. Visit us at Booth #1857, join our exclusive events, and learn how to build in a weekend and scale to millions.', + ogImage: `${SITE_ORIGIN}/images/og/re_invent.png`, }, heroSection: { id: 'hero', diff --git a/apps/www/pages/aws-reinvent-2025.tsx b/apps/www/pages/aws-reinvent-2025.tsx index ffe365344fe..74a4c49b622 100644 --- a/apps/www/pages/aws-reinvent-2025.tsx +++ b/apps/www/pages/aws-reinvent-2025.tsx @@ -21,7 +21,14 @@ const AWSReInvent2025: NextPage = () => { openGraph={{ title: data.metadata.metaTitle, description: data.metadata.metaDescription, - url: `https://supabase.com/aws-reinvent-2025`, + images: [ + { + url: data.metadata.ogImage, + width: 1280, + height: 685, + alt: 'Supabase AWS Re:Invent 2025', + }, + ], }} /> diff --git a/apps/www/public/images/og/re_invent.png b/apps/www/public/images/og/re_invent.png new file mode 100644 index 0000000000000000000000000000000000000000..31cea166148a7df55c437360f72155cd72337d3e GIT binary patch literal 26465 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 literal 0 HcmV?d00001 From 4ee50500119a694284a13a4589445512c6057a0e Mon Sep 17 00:00:00 2001 From: Andrew Agostini Date: Sat, 29 Nov 2025 02:26:29 -0600 Subject: [PATCH 2/6] docs: Fix broken URLS batch 2 (#40484) * docs: update link for Row Level Security documentation in JWT guide * docs: update Figma sign-in link in Flutter guide * docs: force link to Supabase Login with Apple to work (existing relative URL generates incorrect link in live site). * docs: update link for Postgres UUID tutorial * docs: update link for deprecated Android One Tap. Fix broken link to dart signInWithOAuth (the hydrated link on the live site is broken) * docs: update links for MFA enforcement and backup documentation * Update apps/docs/content/guides/auth/quickstarts/with-expo-react-native-social-auth.mdx * Update apps/docs/content/guides/auth/social-login/auth-google.mdx --------- Co-authored-by: Chris Chinchilla --- apps/docs/content/guides/auth/jwts.mdx | 2 +- .../auth/quickstarts/with-expo-react-native-social-auth.mdx | 2 +- apps/docs/content/guides/auth/social-login/auth-figma.mdx | 2 +- apps/docs/content/guides/auth/social-login/auth-google.mdx | 4 ++-- apps/docs/content/guides/database/extensions/uuid-ossp.mdx | 2 +- .../content/guides/deployment/branching/configuration.mdx | 2 +- apps/docs/content/guides/deployment/going-into-prod.mdx | 2 +- .../content/guides/deployment/shared-responsibility-model.mdx | 2 +- .../content/guides/platform/multi-factor-authentication.mdx | 2 +- apps/docs/content/guides/storage/debugging/error-codes.mdx | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/docs/content/guides/auth/jwts.mdx b/apps/docs/content/guides/auth/jwts.mdx index 576a87819cc..aa509cdf027 100644 --- a/apps/docs/content/guides/auth/jwts.mdx +++ b/apps/docs/content/guides/auth/jwts.mdx @@ -8,7 +8,7 @@ A [JSON Web Token](https://jwt.io/introduction) is a type of data structure, rep Supabase Auth continuously issues a new JWT for each user session, for as long as the user remains signed in. Check the comprehensive guide on [Sessions](/docs/guides/auth/sessions) to find out how you can tailor this process for your needs. -JWTs provide the foundation for [Row Level Security](/docs/guides/database/row-level-security). Each Supabase product is able to securely decode and verify the validity of a JWT it receives before using Postgres policies and roles to authorize access to the project's data. +JWTs provide the foundation for [Row Level Security](/docs/guides/database/postgres/row-level-security). Each Supabase product is able to securely decode and verify the validity of a JWT it receives before using Postgres policies and roles to authorize access to the project's data. Supabase provides a comprehensive system of managing [JWT Signing Keys](/docs/guides/auth/signing-keys) used to create and verify JSON Web Tokens. diff --git a/apps/docs/content/guides/auth/quickstarts/with-expo-react-native-social-auth.mdx b/apps/docs/content/guides/auth/quickstarts/with-expo-react-native-social-auth.mdx index 539e3388880..be42dd87c98 100644 --- a/apps/docs/content/guides/auth/quickstarts/with-expo-react-native-social-auth.mdx +++ b/apps/docs/content/guides/auth/quickstarts/with-expo-react-native-social-auth.mdx @@ -572,7 +572,7 @@ npx expo start --tunnel And add it to the **Redirect URLs** field in [your Supabase dashboard Authentication configuration](/dashboard/project/_/auth/url-configuration). -For more information, follow the [Supabase Login with Apple](docs/guides/auth/social-login/auth-apple) guide. +For more information, follow the [Supabase Login with Apple](/docs/guides/auth/social-login/auth-apple) guide. diff --git a/apps/docs/content/guides/auth/social-login/auth-figma.mdx b/apps/docs/content/guides/auth/social-login/auth-figma.mdx index 79eb179aefd..d4da892eaed 100644 --- a/apps/docs/content/guides/auth/social-login/auth-figma.mdx +++ b/apps/docs/content/guides/auth/social-login/auth-figma.mdx @@ -74,7 +74,7 @@ async function signInWithFigma() { -When your user signs in, call [`signInWithOAuth()`](/docs/reference/flutter/auth-signinwithoauth) with `figma` as the `provider`: +When your user signs in, call [`signInWithOAuth()`](/docs/reference/dart/auth-signinwithoauth) with `figma` as the `provider`: ```dart Future signInWithFigma() async { diff --git a/apps/docs/content/guides/auth/social-login/auth-google.mdx b/apps/docs/content/guides/auth/social-login/auth-google.mdx index 332f0cebf2a..f89ef1d61b3 100644 --- a/apps/docs/content/guides/auth/social-login/auth-google.mdx +++ b/apps/docs/content/guides/auth/social-login/auth-google.mdx @@ -571,7 +571,7 @@ Future _nativeGoogleSignIn() async { -Google sign-in with Supabase on Web, macOS, Windows, and Linux is done through the [`signInWithOAuth`](docs/reference/dart/auth-signinwithoauth) method. +Google sign-in with Supabase on Web, macOS, Windows, and Linux is done through the [`signInWithOAuth`](/docs/reference/dart/auth-signinwithoauth) method. This method of signing in is web based, and will open a browser window to perform the sign in. For non-web platforms, the user is brought back to the app via [deep linking](/docs/guides/auth/native-mobile-deep-linking?platform=flutter). @@ -702,7 +702,7 @@ When using [Compose Multiplatform](https://www.jetbrains.com/lp/compose-multipla **Initialize the Supabase Client** -**Note:** You have to create OAuth credentials for both a Web and Android application. [Learn more](https://developers.google.com/identity/one-tap/android/get-started#api-console) +**Note:** You have to create OAuth credentials for both a Web and Android application. [Learn more](https://developer.android.com/identity/legacy/one-tap/legacy-get-started) ```kotlin val supabaseClient = createSupabaseClient( diff --git a/apps/docs/content/guides/database/extensions/uuid-ossp.mdx b/apps/docs/content/guides/database/extensions/uuid-ossp.mdx index a5ce1e05776..78fe470f690 100644 --- a/apps/docs/content/guides/database/extensions/uuid-ossp.mdx +++ b/apps/docs/content/guides/database/extensions/uuid-ossp.mdx @@ -93,4 +93,4 @@ create table contacts ( ## Resources - [Choosing a Postgres Primary Key](/blog/choosing-a-postgres-primary-key) -- [The Basics Of Postgres `UUID` Data Type](https://www.postgresqltutorial.com/postgresql-uuid/) +- [The Basics Of Postgres `UUID` Data Type](https://www.pgtutorial.com/postgresql-tutorial/postgresql-uuid/) diff --git a/apps/docs/content/guides/deployment/branching/configuration.mdx b/apps/docs/content/guides/deployment/branching/configuration.mdx index 08d603d9feb..9e5559a506b 100644 --- a/apps/docs/content/guides/deployment/branching/configuration.mdx +++ b/apps/docs/content/guides/deployment/branching/configuration.mdx @@ -244,4 +244,4 @@ Use the value from the `BRANCH PROJECT ID` column as your `project_id` in the re - Explore [branching integrations](/docs/guides/deployment/branching/integrations) - Learn about [troubleshooting branches](/docs/guides/deployment/branching/troubleshooting) -- Review [branching pricing](/docs/guides/deployment/branching/pricing) +- Review [branching pricing](/docs/guides/platform/manage-your-usage/branching#pricing) diff --git a/apps/docs/content/guides/deployment/going-into-prod.mdx b/apps/docs/content/guides/deployment/going-into-prod.mdx index b88edf58dd6..f611904efb2 100644 --- a/apps/docs/content/guides/deployment/going-into-prod.mdx +++ b/apps/docs/content/guides/deployment/going-into-prod.mdx @@ -55,7 +55,7 @@ After developing your project and deciding it's Production Ready, you should run - You can restore paused projects from the Supabase dashboard. - Upgrade to Pro to guarantee that your project will not be paused for inactivity. - Database backups are not available for download on the Free Plan. - - You can set up your own backup systems using tools like [pg_dump](https://www.postgresqltutorial.com/postgresql-backup-database/) or [wal-g](https://github.com/wal-g/wal-g). + - You can set up your own backup systems using tools like [pg_dump](https://www.postgresql.org/docs/current/app-pgdump.html) or [wal-g](https://github.com/wal-g/wal-g). - Nightly backups for Pro Plan projects are available on the Supabase dashboard for up to 7 days. - Point in Time Recovery (PITR) allows a project to be backed up at much shorter intervals. This provides users an option to restore to any chosen point of up to seconds in granularity. In terms of Recovery Point Objective (RPO), Daily Backups would be suitable for projects willing to lose up to 24 hours worth of data. If a lower RPO is required, enable PITR. - Supabase Projects use disks that offer 99.8-99.9% durability by default. diff --git a/apps/docs/content/guides/deployment/shared-responsibility-model.mdx b/apps/docs/content/guides/deployment/shared-responsibility-model.mdx index ca6460a836d..7b49295fdb8 100644 --- a/apps/docs/content/guides/deployment/shared-responsibility-model.mdx +++ b/apps/docs/content/guides/deployment/shared-responsibility-model.mdx @@ -92,7 +92,7 @@ You can use Supabase to store and process Protected Health Information (PHI). Yo - Signing a Business Associate Agreement (BAA) with Supabase. Submit a [HIPAA add-on request](https://forms.supabase.com/hipaa2) to get started. You will need to be at least on the [Team Plan](/pricing) to sign a BAA with us. - [Marking specific projects as HIPAA projects](/docs/guides/platform/hipaa-projects) and addressing security issues raised by the advisor. - Ensuring [MFA is enabled](/docs/guides/platform/multi-factor-authentication) on all Supabase accounts. - - [Enforce MFA](/docs/guides/platform/org-mfa-enforcement) as a requirement to access the organization + - [Enforce MFA](/docs/guides/platform/mfa/org-mfa-enforcement) as a requirement to access the organization - Enabling [Point in Time Recovery](/docs/guides/platform/backups#point-in-time-recovery) which requires at least a [small compute add-on](/docs/guides/platform/compute-add-ons). - Turning on [SSL Enforcement](/docs/guides/platform/ssl-enforcement). - Enabling [Network Restrictions](/docs/guides/platform/network-restrictions). diff --git a/apps/docs/content/guides/platform/multi-factor-authentication.mdx b/apps/docs/content/guides/platform/multi-factor-authentication.mdx index 068000e9fc9..5d59ed655aa 100644 --- a/apps/docs/content/guides/platform/multi-factor-authentication.mdx +++ b/apps/docs/content/guides/platform/multi-factor-authentication.mdx @@ -36,7 +36,7 @@ For security reasons, we will not be able to restore access to your account if y Once you've enabled MFA for your Supabase user account, you will be prompted to enter your second factor challenge code as seen in your preferred TOTP app. -If you are an organization owner and on the Pro, Team or Enterprise plan, you can enforce that all organization members [must have MFA enabled](/docs/guides/platform/org-mfa-enforcement). +If you are an organization owner and on the Pro, Team or Enterprise plan, you can enforce that all organization members [must have MFA enabled](/docs/guides/platform/mfa/org-mfa-enforcement). ## Disable MFA diff --git a/apps/docs/content/guides/storage/debugging/error-codes.mdx b/apps/docs/content/guides/storage/debugging/error-codes.mdx index c1a500c31ed..6a962f11e91 100644 --- a/apps/docs/content/guides/storage/debugging/error-codes.mdx +++ b/apps/docs/content/guides/storage/debugging/error-codes.mdx @@ -80,7 +80,7 @@ Here's a list of the most common error codes and their potential resolutions: Indicates that the resource is not found or you don't have the correct permission to access it **Resolution:** -- Add a RLS policy to grant permission to the resource. See our [Access Control docs](/docs/guides/storage/uploads/access-control) for more information. +- Add a RLS policy to grant permission to the resource. See our [Access Control docs](/docs/guides/storage/security/access-control) for more information. - Ensure you include the user `Authorization` header - Verify the object exists From f5791c36eebb361cdbded5ca5ee7e103f776c9fb Mon Sep 17 00:00:00 2001 From: Ali Waseem Date: Sun, 30 Nov 2025 05:51:58 -0700 Subject: [PATCH 3/6] fix: copy first row due to failed falsey check (#40909) * updated because of zero falsey value not copying * test: add E2E test for copying first and second row values Adds regression test to verify that users can copy cell values from the first row (index 0) and second row. This prevents the bug where falsy index checks would prevent copying from row 0. Addresses FE-2178 --- .../grid/components/menu/RowContextMenu.tsx | 8 +-- e2e/studio/features/table-editor.spec.ts | 62 +++++++++++++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/apps/studio/components/grid/components/menu/RowContextMenu.tsx b/apps/studio/components/grid/components/menu/RowContextMenu.tsx index cb6920996bb..97b17a89771 100644 --- a/apps/studio/components/grid/components/menu/RowContextMenu.tsx +++ b/apps/studio/components/grid/components/menu/RowContextMenu.tsx @@ -22,7 +22,7 @@ export const RowContextMenu = ({ rows }: RowContextMenuProps) => { function onDeleteRow(p: RowContextMenuItemProps) { const rowIdx = p.props?.rowIdx - if (!rowIdx) return + if (rowIdx === undefined || rowIdx === null) return const row = rows[rowIdx] if (row) tableEditorSnap.onDeleteRows([row]) @@ -30,7 +30,7 @@ export const RowContextMenu = ({ rows }: RowContextMenuProps) => { function onEditRowClick(p: RowContextMenuItemProps) { const rowIdx = p.props?.rowIdx - if (!rowIdx) return + if (rowIdx === undefined || rowIdx === null) return const row = rows[rowIdx] tableEditorSnap.onEditRow(row) @@ -39,7 +39,7 @@ export const RowContextMenu = ({ rows }: RowContextMenuProps) => { const onCopyCellContent = useCallback( (p: RowContextMenuItemProps) => { const rowIdx = p.props?.rowIdx - if (!snap.selectedCellPosition || !rowIdx) return + if (!snap.selectedCellPosition || rowIdx === undefined || rowIdx === null) return const row = rows[rowIdx] const columnKey = snap.gridColumns[snap.selectedCellPosition.idx as number].key @@ -56,7 +56,7 @@ export const RowContextMenu = ({ rows }: RowContextMenuProps) => { const onCopyRowContent = useCallback( (p: RowContextMenuItemProps) => { const rowIdx = p.props?.rowIdx - if (!rowIdx) return + if (rowIdx === undefined || rowIdx === null) return const row = rows[rowIdx] copyToClipboard(JSON.stringify(row)) diff --git a/e2e/studio/features/table-editor.spec.ts b/e2e/studio/features/table-editor.spec.ts index 20151da746b..b70beef93ca 100644 --- a/e2e/studio/features/table-editor.spec.ts +++ b/e2e/studio/features/table-editor.spec.ts @@ -717,4 +717,66 @@ test.describe('table editor', () => { await deleteTable(page, ref, tableNameDataActions) }) + + test('copying cell values from first and second row works', async ({ page, ref }) => { + const tableName = 'pw_table_copy_rows' + const colName = 'pw_column' + + // Ensure we're on editor + if (!page.url().includes('/editor')) { + await page.goto(toUrl(`/project/${ref}/editor?schema=public`)) + await waitForTableToLoad(page, ref) + } + + // Create table and add two rows + await createTable(page, ref, tableName) + await page.getByRole('button', { name: `View ${tableName}`, exact: true }).click() + await page.waitForURL(/\/editor\/\d+\?schema=public$/) + + // Insert first row with value 'first_row_value' + await page.getByTestId('table-editor-insert-new-row').click() + await page.getByRole('menuitem', { name: 'Insert row Insert a new row' }).click() + await page.getByTestId(`${colName}-input`).fill('first_row_value') + await page.getByTestId('action-bar-save-row').click() + await waitForApiResponse(page, 'pg-meta', ref, 'query?key=', { method: 'POST' }) + + // Insert second row with value 'second_row_value' + await page.getByTestId('table-editor-insert-new-row').click() + await page.getByRole('menuitem', { name: 'Insert row Insert a new row' }).click() + await page.getByTestId(`${colName}-input`).fill('second_row_value') + await page.getByTestId('action-bar-save-row').click() + await waitForApiResponse(page, 'pg-meta', ref, 'query?key=', { method: 'POST' }) + + // Wait for grid to be visible + await expect(page.getByRole('grid')).toBeVisible() + + // Right-click on the first row's cell to open context menu + const firstRowCell = page.getByRole('gridcell', { name: 'first_row_value' }) + await expect(firstRowCell).toBeVisible() + await firstRowCell.click({ button: 'right' }) + + // Click "Copy cell" from context menu + await page.getByRole('menuitem', { name: 'Copy cell' }).click() + await page.waitForTimeout(500) + + // Verify first row value was copied + const firstCopiedValue = await page.evaluate(() => navigator.clipboard.readText()) + expect(firstCopiedValue).toBe('first_row_value') + + // Right-click on the second row's cell to open context menu + const secondRowCell = page.getByRole('gridcell', { name: 'second_row_value' }) + await expect(secondRowCell).toBeVisible() + await secondRowCell.click({ button: 'right' }) + + // Click "Copy cell" from context menu + await page.getByRole('menuitem', { name: 'Copy cell' }).click() + await page.waitForTimeout(500) + + // Verify second row value was copied + const secondCopiedValue = await page.evaluate(() => navigator.clipboard.readText()) + expect(secondCopiedValue).toBe('second_row_value') + + // Cleanup + await deleteTable(page, ref, tableName) + }) }) From f9059427abaa2984032e9cee28cf7c3ade3eadee Mon Sep 17 00:00:00 2001 From: Ben <30612894+BenHavis@users.noreply.github.com> Date: Sun, 30 Nov 2025 19:52:51 -0500 Subject: [PATCH 4/6] docs: add explanation of Realtime Broadcast usage in Realtime Chat (#40882) Adds a section explaining that Realtime Chat uses Realtime Broadcast, does not store messages by default, and relies on onMessage for persistence. Improves developer understanding of expected behavior. --- .../content/docs/nextjs/realtime-chat.mdx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps/ui-library/content/docs/nextjs/realtime-chat.mdx b/apps/ui-library/content/docs/nextjs/realtime-chat.mdx index 3010a19f553..7612c3c3204 100644 --- a/apps/ui-library/content/docs/nextjs/realtime-chat.mdx +++ b/apps/ui-library/content/docs/nextjs/realtime-chat.mdx @@ -20,6 +20,19 @@ description: Real-time chat component for collaborative applications The Realtime Chat component provides a complete chat interface that enables users to exchange messages in real-time within a shared room. +## How it works under the hood + +This chat component uses **Supabase Realtime Broadcast** to send and receive messages between connected clients. + +Messages sent through Broadcast are: + +- delivered in real time to other connected clients +- **not stored** unless you handle persistence yourself +- **not guaranteed** to arrive if the client disconnects +- scoped to a specific `roomName`, which corresponds to a broadcast channel + +This design keeps latency extremely low, but it means you should use the `onMessage` callback if you want to store messages permanently or show chat history on page load. + ## Usage ### Basic usage From 4ad48b750d29424bbc8e5d960a4b17c0044b4998 Mon Sep 17 00:00:00 2001 From: Ben <30612894+BenHavis@users.noreply.github.com> Date: Sun, 30 Nov 2025 21:38:48 -0500 Subject: [PATCH 5/6] docs: add presence overview section and example payload (#40635) Adds a brief overview explaining Presence behavior and includes an example presenceState() payload. --------- Co-authored-by: Eduardo Gurgel --- .../docs/content/guides/realtime/presence.mdx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/apps/docs/content/guides/realtime/presence.mdx b/apps/docs/content/guides/realtime/presence.mdx index 46abb1b9070..f99eedb4f4f 100644 --- a/apps/docs/content/guides/realtime/presence.mdx +++ b/apps/docs/content/guides/realtime/presence.mdx @@ -10,6 +10,25 @@ Let's explore how to implement Realtime Presence to track state between multiple You can use the Supabase client libraries to track Presence state between users. +### How Presence works + +Presence lets each connected client publish a small piece of state—called a “presence payload”—to a shared channel. Supabase stores each client’s payload under a unique presence key and keeps a merged view of all connected clients. + +When any client subscribes, disconnects, or updates their presence payload, Supabase triggers one of three events: + +- **`sync`** — the full presence state has been updated +- **`join`** — a new client has started tracking presence +- **`leave`** — a client has stopped tracking presence + +The complete presence state returned by `presenceState()` looks like this: + +```json +{ + "client_key_1": [{ "userId": 1, "typing": false }], + "client_key_2": [{ "userId": 2, "typing": true }] +} +``` + ### Initialize the client Go to your Supabase project's [API Settings](/dashboard/project/_/settings/api) and grab the `URL` and `anon` public API key. From 7facc6265270685079cfabb1bea663fbc1365277 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Mon, 1 Dec 2025 14:08:15 +0800 Subject: [PATCH 6/6] Fix Logs.Datepickers.test.tsx (#40939) --- apps/studio/tests/features/logs/Logs.Datepickers.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/studio/tests/features/logs/Logs.Datepickers.test.tsx b/apps/studio/tests/features/logs/Logs.Datepickers.test.tsx index ebc02f424c0..a56abf92883 100644 --- a/apps/studio/tests/features/logs/Logs.Datepickers.test.tsx +++ b/apps/studio/tests/features/logs/Logs.Datepickers.test.tsx @@ -48,7 +48,7 @@ test('renders dates in local time', async () => { ) // renders time locally await userEvent.click(await screen.findByText(RegExp(from.format('DD MMM')))) - await screen.findByText(RegExp(from.format('MMMM YYYY'))) + await screen.findByText(RegExp(from.format('DD MMM'))) }) test('renders datepicker selected dates in local time', async () => {