@@ -777,6 +777,95 @@ export default scenario("Full Stack Test", {
777777
778778## Best Practices
779779
780+ ### Make Step Dependencies Explicit
781+
782+ Keep steps in the same scenario only when they need data from ` ctx.previous ` .
783+ If a step does not read the previous result, extract it into its own scenario
784+ and share a resource factory instead.
785+
786+ ``` typescript
787+ import { client , scenario } from " jsr:@probitas/probitas" ;
788+
789+ const http = () =>
790+ client .http .createHttpClient ({
791+ url: Deno .env .get (" API_URL" ) ?? " http://localhost:8080" ,
792+ });
793+
794+ // Avoid - unrelated steps bundled together
795+ scenario (" User checks" )
796+ .resource (" http" , http )
797+ .step (" Create user" , async (ctx ) => {
798+ await ctx .resources .http .post (" /users" , { body: { name: " Alice" } });
799+ })
800+ .step (" List users" , async (ctx ) => {
801+ await ctx .resources .http .get (" /users" );
802+ })
803+ .build ();
804+
805+ // Good - separate scenarios that can run independently
806+ export default [
807+ scenario (" Create user" ).resource (" http" , http ).step (() => {}).build (),
808+ scenario (" List users" ).resource (" http" , http ).step (() => {}).build (),
809+ ];
810+ ```
811+
812+ ### Finish Builders and Exports
813+
814+ Every scenario must end with ` .build() ` and be exported as ` export default ` ,
815+ either as a single scenario or an array of scenarios.
816+
817+ ``` typescript
818+ // Correct - single scenario
819+ export default scenario (" Example" ).step (() => {}).build ();
820+
821+ // Correct - multiple scenarios
822+ export default [
823+ scenario (" First" ).step (() => {}).build (),
824+ scenario (" Second" ).step (() => {}).build (),
825+ ];
826+ ```
827+
828+ ### Use Environment-Driven URLs
829+
830+ Parameterize endpoints so tests run consistently across environments and avoid
831+ hard-coding localhost URLs.
832+
833+ ``` typescript
834+ import { client , scenario } from " jsr:@probitas/probitas" ;
835+
836+ const apiUrl = Deno .env .get (" API_URL" ) ?? " http://localhost:8080" ;
837+
838+ export default scenario (" API test" )
839+ .resource (" http" , () => client .http .createHttpClient ({ url: apiUrl }))
840+ .step (() => {})
841+ .build ();
842+ ```
843+
844+ ### Prefer Fluent Assertions
845+
846+ Use ` expect() ` chains instead of manual ` if/throw ` checks, and keep related
847+ assertions in a single chain for clearer failures.
848+
849+ ``` typescript
850+ import { client , expect } from " jsr:@probitas/probitas" ;
851+
852+ await using http = client .http .createHttpClient ({
853+ url: " http://localhost:8080" ,
854+ });
855+ const res = await http .get (" /users/1" );
856+
857+ // Avoid - manual checks
858+ if (res .status !== 200 ) {
859+ throw new Error (` Expected 200, got ${res .status } ` );
860+ }
861+
862+ // Good - fluent assertions
863+ expect (res )
864+ .toBeOk ()
865+ .toHaveStatus (200 )
866+ .not .toHaveJsonProperty ([" metadata" , " x-internal-token" ]);
867+ ```
868+
780869### Use Descriptive Step Names
781870
782871Good names make test output readable and debugging easier.
@@ -1148,3 +1237,12 @@ export default [
11481237 .build (),
11491238];
11501239```
1240+
1241+ ## Common Mistakes
1242+
1243+ - Forgetting ` export default ` or ` .build() ` when returning the scenario builder
1244+ - Bundling independent tests in one scenario instead of splitting them when
1245+ they do not use ` ctx.previous `
1246+ - Hard-coding endpoints instead of using environment-driven URLs
1247+ - Using manual ` if/throw ` checks instead of fluent ` expect() ` chains
1248+ - Omitting cleanup functions from ` .setup() ` when creating external fixtures
0 commit comments