Skip to content

Commit d6da2d4

Browse files
authored
test(react-sdk): add example app verification (#1162)
<!-- CURSOR_SUMMARY --> > [!NOTE] > **Medium Risk** > Primarily CI/test additions, but it introduces new GitHub Actions jobs that assume an AWS role and pull secrets via OIDC/SSM, so misconfiguration could impact CI or secret access paths. > > **Overview** > Adds automated e2e verification of the React `examples/client-only` app using Playwright, including a new `playwright.config.ts`, a basic spec, and wiring `yarn test` into the example workspace. > > Introduces a reusable composite action `actions/run-example` that installs the target workspace, fetches required LaunchDarkly keys from AWS SSM via OIDC, builds dependent workspaces, and runs the example tests; this action is executed in the main `react.yaml` workflow and a new scheduled `react-nightly.yaml` workflow. The example app now reads the flag key from `import.meta.env.LAUNCHDARKLY_FLAG_KEY`, and Playwright `test-results/` are ignored. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 7b2f38f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/launchdarkly/js-core/pull/1162" target="_blank"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin"> </picture> </a> <!-- devin-review-badge-end -->
1 parent 2de5c27 commit d6da2d4

8 files changed

Lines changed: 115 additions & 1 deletion

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: sdk/react nightly
2+
3+
on:
4+
schedule:
5+
- cron: '0 0 * * *'
6+
7+
jobs:
8+
run-example:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
id-token: write
12+
steps:
13+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
14+
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
15+
with:
16+
node-version: 22
17+
- uses: ./actions/run-example
18+
with:
19+
workspace_name: '@internal/react-sdk-example-client-only'
20+
aws_assume_role: ${{ vars.AWS_ROLE_ARN }}
21+
before_test: 'yarn workspace @internal/react-sdk-example-client-only playwright install --with-deps chromium'

.github/workflows/react.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,20 @@ jobs:
8181
[ -f /tmp/browser.pid ] && kill $(cat /tmp/browser.pid) || true
8282
[ -f /tmp/entity.pid ] && kill $(cat /tmp/entity.pid) || true
8383
[ -f /tmp/adapter.pid ] && kill $(cat /tmp/adapter.pid) || true
84+
85+
run-example:
86+
runs-on: ubuntu-latest
87+
permissions:
88+
id-token: write
89+
steps:
90+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
91+
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
92+
with:
93+
node-version: 22
94+
- uses: ./actions/run-example
95+
with:
96+
workspace_name: '@internal/react-sdk-example-client-only'
97+
aws_assume_role: ${{ vars.AWS_ROLE_ARN }}
98+
before_test: 'yarn workspace @internal/react-sdk-example-client-only playwright install --with-deps chromium'
99+
100+
# TODO: Add contract tests

actions/run-example/action.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Composite action for running an example app e2e test.
2+
# Note: id-token: write permission must be declared on the calling job.
3+
name: Run Example App
4+
inputs:
5+
workspace_name:
6+
description: 'Yarn workspace name of the example app, e.g. @internal/react-sdk-example-client-only'
7+
required: true
8+
aws_assume_role:
9+
description: 'AWS OIDC role ARN used to fetch secrets from SSM'
10+
required: true
11+
before_test:
12+
description: 'Shell commands to run before the e2e test step (e.g. install Playwright browsers)'
13+
default: ''
14+
runs:
15+
using: composite
16+
steps:
17+
- name: Install dependencies
18+
shell: bash
19+
run: yarn workspaces focus ${{ inputs.workspace_name }}
20+
21+
- uses: launchdarkly/gh-actions/actions/release-secrets@bbbbbda684f500766264e7fe327668094ba83d1c
22+
name: 'Get the client-side SDK key'
23+
with:
24+
aws_assume_role: ${{ inputs.aws_assume_role }}
25+
ssm_parameter_pairs: '/sdk/common/hello-apps/client-key = LAUNCHDARKLY_CLIENT_SIDE_ID'
26+
27+
- uses: launchdarkly/gh-actions/actions/release-secrets@bbbbbda684f500766264e7fe327668094ba83d1c
28+
name: 'Get the test feature flag key'
29+
with:
30+
aws_assume_role: ${{ inputs.aws_assume_role }}
31+
ssm_parameter_pairs: '/sdk/common/hello-apps/boolean-flag-key = LAUNCHDARKLY_FLAG_KEY'
32+
33+
- name: Build SDK dependencies
34+
shell: bash
35+
run: yarn workspaces foreach -pR --topological-dev --from '${{ inputs.workspace_name }}' run build
36+
37+
- name: Before test hook
38+
shell: bash
39+
if: ${{ inputs.before_test != '' }}
40+
run: ${{ inputs.before_test }}
41+
42+
- name: Run e2e tests
43+
shell: bash
44+
run: yarn workspace ${{ inputs.workspace_name }} test

packages/sdk/react/examples/client-only/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@
1919
npm-debug.log*
2020
yarn-debug.log*
2121
yarn-error.log*
22+
23+
test-results/
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { expect, test } from '@playwright/test';
2+
3+
test('feature flag evaluates to true', async ({ page }) => {
4+
await page.goto('/');
5+
6+
await expect(page.getByText('SDK successfully initialized!')).toBeVisible({ timeout: 10000 });
7+
8+
await expect(page.getByText(`feature flag evaluates to true`, { exact: false })).toBeVisible({
9+
timeout: 10000,
10+
});
11+
});

packages/sdk/react/examples/client-only/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
"start": "vite",
1212
"build": "vite build",
1313
"preview": "vite preview",
14+
"test": "playwright test",
1415
"tsc": "tsc"
1516
},
1617
"devDependencies": {
18+
"@playwright/test": "^1.49.1",
1719
"@types/node": "^16.18.18",
1820
"@types/react": "^18.0.28",
1921
"@types/react-dom": "^18.0.11",
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// eslint-disable-next-line import/no-extraneous-dependencies
2+
import { defineConfig } from '@playwright/test';
3+
4+
export default defineConfig({
5+
testDir: './e2e',
6+
timeout: 30_000,
7+
reporter: [['list']],
8+
use: {
9+
baseURL: 'http://localhost:4173',
10+
},
11+
webServer: {
12+
command: 'yarn preview',
13+
port: 4173,
14+
timeout: 30_000,
15+
reuseExistingServer: !process.env.CI,
16+
},
17+
});

packages/sdk/react/examples/client-only/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
import './App.css';
1111

1212
// Set FLAG_KEY to the feature flag key you want to evaluate.
13-
const FLAG_KEY = 'sample-feature';
13+
const FLAG_KEY = import.meta.env.LAUNCHDARKLY_FLAG_KEY ?? 'sample-feature';
1414

1515
const PRESET_CONTEXTS: ReadonlyArray<LDContext> = [
1616
{ kind: 'user', key: 'example-user-key', name: 'Sandy' },

0 commit comments

Comments
 (0)