Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -383,14 +383,16 @@ jobs:
# report-handler and wrapper-channel suites, whose timing windows (a
# 25 s deadline asserted to within a second) a shared runner cannot
# promise, and which retain bundles -- on iOS beta3 those carry
# credentials, and CI has no policy for keeping them.
# credentials, and CI has no policy for keeping them. Jest reads the
# argument as a regex over the path: anchored, so a file whose name
# merely contains "launch.test.ts" (api-relaunch.test.ts) stays out.
- name: Reach Status.Launched
working-directory: examples/bare
env:
E2E_PLATFORM: ios
E2E_IOS_TARGET: simulator
IOS_SIMULATOR_ID: ${{ steps.sim.outputs.udid }}
run: yarn e2e launch.test.ts
run: yarn e2e '/launch\.test\.ts$'

# The e2e reads only the console pty. The app's own persisted log says
# whether a missing marker was never logged or logged and not streamed.
Expand Down
47 changes: 47 additions & 0 deletions examples/bare/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ import {
} from './smoke/scenarios';
import { isInfraScenario, runInfraScenario } from './scenarios/infra';
import { FlowStage, isFlowScenario, preLaunchFlow, runFlowScenario } from './scenarios/flows';
import {
ApiStage,
type ApiStageState,
apiLaunchOverrides,
isApiScenario,
preLaunchApi,
runApiScenario,
} from './scenarios/api';

const STATUS_NAMES: Record<number, string> = {
[Status.Stopped]: 'Stopped',
Expand Down Expand Up @@ -167,6 +175,8 @@ function launchOptions(endpoint: string, scenario: string): LaunchOptions {
// set, through setCustomOption -- the typed model's escape hatch, which
// writes the same native payload a first-class accessor does.
launchOverrides(scenario, (key, value) => options.setCustomOption(key, value));
// The campaign API scenarios (scenarios/api.tsx), on the typed model.
apiLaunchOverrides(scenario, options);
const serialized = BugseeLaunchOptions.serialize(options) as LaunchOptions;
// This scenario only. APM is on by default; setting the key makes the
// launch explicit about the capture this scenario is here to produce.
Expand Down Expand Up @@ -294,6 +304,8 @@ export default function App() {
>();
/** Set before launch for the campaign flow scenarios (scenarios/flows.tsx). */
const [flowStage, setFlowStage] = useState<string | undefined>();
/** Set by a campaign API scenario that puts something on screen (scenarios/api.tsx). */
const [apiStage, setApiStage] = useState<ApiStageState | undefined>();

useEffect(() => {
let cancelled = false;
Expand Down Expand Up @@ -440,6 +452,26 @@ export default function App() {
poll = setInterval(() => {
Bugsee.getStatus().then(observe).catch(() => {});
}, 100);
// The campaign API scenarios' pre-launch step. `true`: the scenario
// owns the launch (api-attach on a manifest-launched build).
if (isApiScenario(choice.scenario)) {
try {
const apiContext = {
token,
options: () => launchOptions(endpoint, choice.scenario),
setStage: (next: ApiStageState | undefined) => {
if (!cancelled) {
setApiStage(next);
}
},
};
if (await preLaunchApi(choice.scenario, choice.nonce, apiContext)) {
return;
}
} catch (apiCause) {
console.log(`BUGSEE_E2E api pre-launch threw ${String(apiCause)}`);
}
}
try {
const launched = await Bugsee.launch(token, launchOptions(endpoint, choice.scenario));
console.log(`BUGSEE_E2E launch() resolved ${String(launched)}`);
Expand Down Expand Up @@ -558,6 +590,20 @@ export default function App() {
return;
}

// The campaign API scenarios (scenarios/api.tsx).
if (isApiScenario(choice.scenario)) {
await runApiScenario(choice.scenario, choice.nonce, {
token,
options: () => launchOptions(endpoint, choice.scenario),
setStage: next => {
if (!cancelled) {
setApiStage(next);
}
},
});
return;
}

// The campaign harness's helper proofs (scenarios/infra.ts).
if (isInfraScenario(choice.scenario)) {
await runInfraScenario(choice.scenario, choice.nonce);
Expand Down Expand Up @@ -710,6 +756,7 @@ export default function App() {
<SmokeStage scenario={smokeStage.scenario} nonce={smokeStage.nonce} />
)}
{flowStage !== undefined && <FlowStage />}
{apiStage !== undefined && <ApiStage stage={apiStage} />}
</View>
);
}
Expand Down
12 changes: 12 additions & 0 deletions examples/bare/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@ android {
keyPassword 'android'
}
}
// Campaign N-02 (e2e/attach.test.ts): `-PbugseeE2eAutoLaunch=true` merges
// src/e2eAutoLaunch/AndroidManifest.xml into the debug build, so the SDK
// launches itself from `com.bugsee.app-token` meta-data (the placeholder
// token, against the dead endpoint) before any JS runs. Off by default:
// a build without the property has no such meta-data.
if (findProperty('bugseeE2eAutoLaunch') == 'true') {
sourceSets {
debug {
manifest.srcFile 'src/e2eAutoLaunch/AndroidManifest.xml'
}
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
Expand Down
17 changes: 17 additions & 0 deletions examples/bare/android/app/src/e2eAutoLaunch/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Campaign N-02 only (e2e/attach.test.ts): merged into the debug build when
it is made with -PbugseeE2eAutoLaunch=true. The SDK's BugseeInitProvider
then launches from this meta-data before any JS runs: the placeholder
token, never a real one, against the closed loopback endpoint.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<meta-data
android:name="com.bugsee.app-token"
android:value="00000000-0000-4000-8000-000000000000" />
<meta-data
android:name="com.bugsee.option.$$ENDPOINT"
android:value="https://127.0.0.1:9" />
</application>
</manifest>
Loading
Loading