Skip to content

Commit 521e8f5

Browse files
committed
Apply the review of the live suite
Moves the build env and inputs to apps/sim/turbo.json, where @sim/app reads them: its own override discarded the root edit, so the zone and no-zone builds hashed alike. Reads the proxy's mode from the one resolver, makes ActionMenu's icon required so a row menu cannot silently become a text button, wraps property values rather than labels, moves platformOrgUi off navFlags, and tidies the seed, specs and parity audit.
1 parent 07c80cf commit 521e8f5

27 files changed

Lines changed: 244 additions & 244 deletions

File tree

‎.github/scripts/ci-plan.gql‎

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,59 @@
1-
query($base: String!, $head: String!) {
2-
packages { items { name path } }
3-
affectedTasks(base: $base, head: $head, tasks: [
4-
"test", "build", "type-check", "ci:integration", "ci:desktop-live",
5-
"ci:e2e-scim", "ci:e2e-cli", "ci:e2e-stop-after", "ci:e2e-desktop-inbox",
6-
"ci:e2e-assistant-actions", "ci:e2e-organization-search",
7-
"ci:e2e-docs-platform",
8-
"ci:e2e-browser-extension", "ci:e2e-project-files", "ci:e2e-mobile", "ci:e2e-seo"
9-
]) {
1+
query ($base: String!, $head: String!) {
2+
packages {
3+
items {
4+
name
5+
path
6+
}
7+
}
8+
affectedTasks(
9+
base: $base
10+
head: $head
11+
tasks: [
12+
"test"
13+
"build"
14+
"type-check"
15+
"ci:integration"
16+
"ci:desktop-live"
17+
"ci:e2e-scim"
18+
"ci:e2e-cli"
19+
"ci:e2e-stop-after"
20+
"ci:e2e-desktop-inbox"
21+
"ci:e2e-assistant-actions"
22+
"ci:e2e-organization-search"
23+
"ci:e2e-docs-platform"
24+
"ci:e2e-browser-extension"
25+
"ci:e2e-project-files"
26+
"ci:e2e-mobile"
27+
"ci:e2e-seo"
28+
]
29+
) {
1030
items {
1131
name
1232
fullName
13-
package { name }
33+
package {
34+
name
35+
}
1436
reason {
1537
__typename
16-
... on TaskFileChanged { filePath }
17-
... on TaskGlobalFileChanged { filePath }
18-
... on TaskGlobalDepsChanged { filePath }
19-
... on TaskDependencyTaskChanged { taskName packageName }
20-
... on TaskPackageDependencyChanged { packageName }
21-
... on TaskAllChanged { description }
38+
... on TaskFileChanged {
39+
filePath
40+
}
41+
... on TaskGlobalFileChanged {
42+
filePath
43+
}
44+
... on TaskGlobalDepsChanged {
45+
filePath
46+
}
47+
... on TaskDependencyTaskChanged {
48+
taskName
49+
packageName
50+
}
51+
... on TaskPackageDependencyChanged {
52+
packageName
53+
}
54+
... on TaskAllChanged {
55+
description
56+
}
2257
}
2358
}
2459
}

‎.github/scripts/http-e2e.sh‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,11 @@ platform_live_environment() {
207207
bun --no-env-file scripts/platform-live-seed.ts
208208
}
209209

210-
# run_platform_live <project> <report-name> [playwright args...]
210+
# run_platform_live <project> <report-name>
211211
run_platform_live() {
212212
local project=$1 name=$2
213-
shift 2
214213
PLATFORM_LIVE_REPORT_PATH="$report_dir/$name/report.json" \
215-
bun run test:platform:live --project="$project" ${PLATFORM_LIVE_GREP:+--grep "$PLATFORM_LIVE_GREP"} "$@"
214+
bun run test:platform:live --project="$project" ${PLATFORM_LIVE_GREP:+--grep "$PLATFORM_LIVE_GREP"}
216215
}
217216

218217
# wait_ready <pid> <health-url> <label>

‎.github/workflows/platform-design.yml‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ on:
44
pull_request:
55
paths:
66
- 'apps/sim/platform/**'
7+
- '!apps/sim/platform/docs/**'
8+
- '!apps/sim/platform/README.md'
79
- 'apps/sim/package.json'
810
- 'scripts/check-platform-design*'
911
- 'scripts/platform-variant-usage.ts'
@@ -130,6 +132,7 @@ jobs:
130132
with:
131133
provider: ${{ vars.CI_PROVIDER }}
132134
turbo-cache-key: turbo-cache-platform-live-${{ matrix.topology }}
135+
- run: bun run check:platform-parity
133136
- name: Provision the database through migrations
134137
working-directory: packages/db
135138
run: bun run db:migrate
@@ -159,7 +162,7 @@ jobs:
159162
- name: Hold the parity ledger to this run
160163
if: always() && matrix.topology == 'zone'
161164
run: >-
162-
bun run scripts/check-platform-parity.ts
165+
bun run check:platform-parity
163166
--report "$RUNNER_TEMP/e2e/platform-live/report.json"
164167
--report "$RUNNER_TEMP/e2e/platform-live-flag-off/report.json"
165168
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2

‎apps/sim/lib/api/contracts/organization.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,10 +554,10 @@ const organizationSurfaceResponseSchema = z.object({
554554
selfHosted: z.record(z.string(), z.boolean().optional()),
555555
}),
556556
deployment: deploymentShapeSchema,
557+
/** Whether the Platform zone is open to this organization at all. */
558+
platformOrgUi: z.boolean(),
557559
/** Which destinations the viewer's navigation lists; none of these authorizes the page behind it. */
558560
navFlags: z.object({
559-
/** Whether the Platform zone is open to this organization at all. */
560-
platformOrgUi: z.boolean(),
561561
people: z.boolean(),
562562
simLinks: z.boolean(),
563563
benchmark: z.boolean(),

‎apps/sim/lib/organizations/application/surface.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ export const readOrganizationSurface: OperationUseCase<
7373
connectedAccountsAvailable: context.connectedAccountsAvailable,
7474
settingsFeatures: context.settingsFeatures,
7575
deployment: context.deployment,
76+
platformOrgUi,
7677
navFlags: {
77-
platformOrgUi,
7878
people,
7979
simLinks,
8080
benchmark: benchmarkEnabled,

‎apps/sim/platform/app/(shell)/_components/live-shell/live-shell.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export async function LiveShell({ children }: { children: ReactNode }) {
2727

2828
const { organization } = surface
2929
// Deployed, the zone exists only for an organization the rollout has reached.
30-
if (process.env.NEXT_PUBLIC_SIM_PLATFORM_BASE_PATH && !organization.navFlags.platformOrgUi) {
30+
if (process.env.NEXT_PUBLIC_SIM_PLATFORM_BASE_PATH && !organization.platformOrgUi) {
3131
notFound()
3232
}
3333
const cookieStore = await cookies()

‎apps/sim/platform/app/(shell)/_components/sidebar/help-menu.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export function HelpMenu({ iconOnly, help = SESSION_HELP }: HelpMenuProps) {
8989
<ActionMenu
9090
label='Help'
9191
triggerSize='row'
92-
icon={iconOnly ? 'I047' : undefined}
92+
icon={iconOnly ? 'I047' : null}
9393
actions={actions}
9494
/>
9595
{support.submit && contacting && (

‎apps/sim/platform/checks/live/flag-off/legacy-surface.spec.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect, type Page, test } from '@playwright/test'
2-
import { adminEmail, organizationId, signIn } from '@/platform/checks/live/session'
2+
import { organizationId, signInAsAdmin } from '@/platform/checks/live/session'
33

44
/**
55
* Runs twice: built with no `SIM_PLATFORM_ORIGIN`, with the flag on; and built with the zone, with
@@ -19,21 +19,21 @@ async function expectLegacySurface(page: Page, route: string) {
1919

2020
for (const route of LEGACY_ROUTES) {
2121
test(`/o/[id]/${route} renders the legacy surface with no redirect`, async ({ page }) => {
22-
await signIn(page, adminEmail(), `/o/${organizationId()}/${route}`)
22+
await signInAsAdmin(page, `/o/${organizationId()}/${route}`)
2323
await expectLegacySurface(page, route)
2424
})
2525
}
2626

2727
test('a client navigation stays on the legacy surface too', async ({ page }) => {
28-
await signIn(page, adminEmail(), `/o/${organizationId()}/home`)
28+
await signInAsAdmin(page, `/o/${organizationId()}/home`)
2929
await page.getByRole('link', { name: 'People', exact: true }).first().click()
3030
await expect(page).toHaveURL(new RegExp(`/o/${organizationId()}/people`))
3131
await expect(page.locator('[data-platform-ui]')).toHaveCount(0)
3232
})
3333

3434
test('/org is absent', async ({ page }) => {
35+
await signInAsAdmin(page, `/o/${organizationId()}/home`)
3536
for (const path of ['/org', '/org/home', '/org/settings/members']) {
36-
await signIn(page, adminEmail(), `/o/${organizationId()}/home`)
3737
const response = await page.goto(path)
3838
expect(response?.status(), path).toBe(404)
3939
await expect(page.getByRole('button', { name: 'Organization menu' })).toHaveCount(0)

‎apps/sim/platform/checks/live/flows.spec.ts‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { expect, type Page, test } from '@playwright/test'
2-
import { adminEmail, signIn, signInAsAdmin } from '@/platform/checks/live/session'
2+
import { escapeRegExp } from '@sim/utils/string'
3+
import { adminEmail, requireEnv, signInAsAdmin } from '@/platform/checks/live/session'
34

45
/** What a member does day to day beyond each section's own spec, against the real API. */
56
const chats = (page: Page) => page.getByRole('region', { name: 'Chats', exact: true })
67
const workspaces = (page: Page) => page.getByRole('region', { name: 'Workspaces', exact: true })
78

89
test('a chat pins and marks unread, and both survive a reload', async ({ page }) => {
9-
await signInAsAdmin(page, '/org/settings/members')
10-
await page.goto('/org/home')
10+
await signInAsAdmin(page, '/org/home')
1111
const list = chats(page)
1212
await list.getByRole('button', { name: 'Actions for Quarterly review' }).click()
1313
await page.getByRole('menuitem', { name: 'Pin', exact: true }).click()
@@ -112,10 +112,10 @@ test('member search lives in the URL and narrows the roster', async ({ page }) =
112112
await page.getByRole('searchbox', { name: /Search members/ }).fill(adminEmail())
113113
await expect(page).toHaveURL(/search=/)
114114
await expect(page.getByText(adminEmail()).first()).toBeVisible()
115-
await expect(page.getByText(process.env.PLATFORM_LIVE_OWNER_EMAIL as string)).toHaveCount(0)
115+
await expect(page.getByText(requireEnv('PLATFORM_LIVE_OWNER_EMAIL'))).toHaveCount(0)
116116
await page.reload()
117117
await expect(page.getByRole('searchbox', { name: /Search members/ })).toHaveValue(adminEmail())
118-
await expect(page.getByText(process.env.PLATFORM_LIVE_OWNER_EMAIL as string)).toHaveCount(0)
118+
await expect(page.getByText(requireEnv('PLATFORM_LIVE_OWNER_EMAIL'))).toHaveCount(0)
119119
})
120120

121121
test('a notification preference writes and survives a reload', async ({ page }) => {
@@ -152,7 +152,7 @@ test('a permission group created in the form opens, saves its name and deletes',
152152
await dialog.getByText('Make this the organization default group').click()
153153
await dialog.getByRole('button', { name: 'Create', exact: true }).click()
154154
await expect(dialog).toBeHidden()
155-
await page.getByRole('button', { name: new RegExp(`^${name}`) }).click()
155+
await page.getByRole('button', { name: new RegExp(`^${escapeRegExp(name)}`) }).click()
156156
await expect(page).toHaveURL(/group-id=/)
157157
await page.reload()
158158
await expect(page.getByRole('textbox', { name: 'Name' })).toHaveValue(name)
@@ -172,6 +172,6 @@ test('Requests opens for an administrator and switches views in the URL', async
172172
})
173173

174174
test('an unknown settings section is not found, inside the shell', async ({ page }) => {
175-
await signIn(page, adminEmail(), '/org/settings/not-a-section')
175+
await signInAsAdmin(page, '/org/settings/not-a-section')
176176
await expect(page.getByRole('heading', { name: 'Page not found' })).toBeVisible()
177177
})

‎apps/sim/platform/checks/live/home.spec.ts‎

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,13 @@ test.describe('Home with connected accounts', () => {
200200
}
201201
}
202202

203-
async function serveWidgets(page: Page) {
204-
await page.route('**/home/email', (route) =>
205-
route.fulfill({ json: { accounts: [account(GRANT, 'ready')], threads: THREADS } })
206-
)
203+
const READY_MAIL = { accounts: [account(GRANT, 'ready')], threads: THREADS }
204+
205+
async function serveWidgets(
206+
page: Page,
207+
mail: { status?: number; json: unknown } = { json: READY_MAIL }
208+
) {
209+
await page.route('**/home/email', (route) => route.fulfill(mail))
207210
await page.route('**/home/calendar?*', (route) => {
208211
const date = new URL(route.request().url()).searchParams.get('date') as string
209212
return route.fulfill({ json: calendarFor(date) })
@@ -248,7 +251,7 @@ test.describe('Home with connected accounts', () => {
248251
await page.route('**/home/email', (route) =>
249252
failing
250253
? route.fulfill({ status: 500, json: { error: 'Provider down' } })
251-
: route.fulfill({ json: { accounts: [account(GRANT, 'ready')], threads: THREADS } })
254+
: route.fulfill({ json: READY_MAIL })
252255
)
253256
await open(page)
254257
const email = page.getByRole('region', { name: 'Email', exact: true })
@@ -264,10 +267,7 @@ test.describe('Home with connected accounts', () => {
264267
test('an account Google stopped honoring asks to reconnect, here and in attention', async ({
265268
page,
266269
}) => {
267-
await serveWidgets(page)
268-
await page.route('**/home/email', (route) =>
269-
route.fulfill({ json: { accounts: [account(GRANT, 'needs_reauth')], threads: [] } })
270-
)
270+
await serveWidgets(page, { json: { accounts: [account(GRANT, 'needs_reauth')], threads: [] } })
271271
await open(page)
272272
await expect(
273273
page
@@ -282,10 +282,7 @@ test.describe('Home with connected accounts', () => {
282282
test('a connected member with an empty mailbox sees that, not a prompt to connect', async ({
283283
page,
284284
}) => {
285-
await serveWidgets(page)
286-
await page.route('**/home/email', (route) =>
287-
route.fulfill({ json: { accounts: [account(GRANT, 'ready')], threads: [] } })
288-
)
285+
await serveWidgets(page, { json: { accounts: [account(GRANT, 'ready')], threads: [] } })
289286
await open(page)
290287
const email = page.getByRole('region', { name: 'Email', exact: true })
291288
await expect(email.getByText('No email yet', { exact: true })).toBeVisible()

0 commit comments

Comments
 (0)