Skip to content

Commit

Permalink
Merge branch 'main' into watch-build
Browse files Browse the repository at this point in the history
  • Loading branch information
slavingia authored Jan 2, 2025
2 parents 5cf8608 + 02f111f commit 74b318e
Show file tree
Hide file tree
Showing 35 changed files with 1,275 additions and 324 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ yarn-error.log*
# local env files
.env
.env.local
.env*.local

# vercel
.vercel
Expand Down
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"tabWidth": 2,
"useTabs": false,
"trailingComma": "all"
}
65 changes: 53 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,14 @@ If helpful, [here's a short video](https://github.com/anti-work/shortest/issues/
npm install -D @antiwork/shortest
# or
pnpm add -D @antiwork/shortest
# or
yarn add -D @antiwork/shortest
```

Add `.shortest/` to your `.gitignore` (where Shortest stores screenshots of each test run):
Add `.shortest/` to your `.gitignore` (where Shortest stores screenshots and caching of each test run):

```bash
echo ".shortest/" >> .gitignore
```

If you installed shortest without `-g` flag, you can run tests as follows:

```bash
npx shortest # for npm
pnpm shortest # for pnpm
yarn shortest # for yarn
```

### Quick start

1. Determine your test entry and add your Anthropic API key in config file: `shortest.config.ts`
Expand All @@ -56,7 +46,7 @@ import type { ShortestConfig } from "@antiwork/shortest";
export default {
headless: false,
baseUrl: "http://localhost:3000",
testDir: "app/__tests__",
testPattern: "**/*.test.ts",
anthropicKey: process.env.ANTHROPIC_API_KEY,
} satisfies ShortestConfig;
```
Expand Down Expand Up @@ -140,6 +130,57 @@ shortest.afterAll(async ({ page }) => {
});
```

### Chaining tests

Shortest supports flexible test chaining patterns:

```typescript
// Sequential test chain
shortest([
"user can login with email and password",
"user can modify their account-level refund policy",
]);

// Reusable test flows
const loginAsLawyer = "login as lawyer with valid credentials";
const loginAsContractor = "login as contractor with valid credentials";
const allAppActions = ["send invoice to company", "view invoices"];

// Combine flows with spread operator
shortest([loginAsLawyer, ...allAppActions]);
shortest([loginAsContractor, ...allAppActions]);
```

### API Testing

Test API endpoints using natural language

```typescript
const req = new APIRequest({
baseURL: API_BASE_URI,
});

shortest(
"Ensure the response contains only active users",
req.fetch({
url: "/users",
method: "GET",
params: new URLSearchParams({
active: true,
}),
}),
);
```

Or simply:

```typescript
shortest(`
Test the API GET endpoint ${API_BASE_URI}/users with query parameter { "active": true }
Expect the response to contain only active users
`);
```

### Running tests

```bash
Expand Down
5 changes: 5 additions & 0 deletions app/(dashboard)/page.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { shortest } from "@antiwork/shortest";

shortest("Verify that buttons on the landing page are rounded");
shortest("Login using this email: mission-health@rdt7stzf.mailosaur.net");
shortest("Verify that the user can access the /dashboard page");
6 changes: 0 additions & 6 deletions app/__tests__/dashboard.test.ts

This file was deleted.

28 changes: 28 additions & 0 deletions app/api/test/assert-bearer/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { NextResponse } from "next/server";
import { ALLOWED_TEST_BEARER } from "@/lib/constants";
import { getBearerToken } from "@/lib/utils-server";

/**
* Asserts that the bearer token is present in the request
* If yes, returns the request body
*/
export async function POST(req: Request) {
const token = getBearerToken(req);

if (!token || token !== ALLOWED_TEST_BEARER) {
return NextResponse.json(
{ message: "Bearer token is missing in cookies" },
{ status: 401 },
);
}

try {
const body = await req.json();
return NextResponse.json(body);
} catch {
return NextResponse.json(
{ message: "Invalid request body" },
{ status: 400 },
);
}
}
22 changes: 18 additions & 4 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import typescriptEslintParser from "@typescript-eslint/parser";

export default [
{
ignores: ["node_modules/**", "dist/**", ".next/**", "packages/shortest/node_modules/**", "packages/shortest/dist/**", "**/*.d.ts"],
ignores: [
"node_modules/**",
"dist/**",
".next/**",
"packages/shortest/node_modules/**",
"packages/shortest/dist/**",
],
},
{
files: ["**/*.ts", "**/*.tsx"],
Expand All @@ -28,14 +34,22 @@ export default [
},
rules: {
"react/react-in-jsx-scope": "off",
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_" },
],
"import/order": ["error", { alphabetize: { order: "asc" } }],
"prettier/prettier": "error",
"prettier/prettier": [
"error",
{
trailingComma: "all",
},
],
},
settings: {
react: {
version: "detect",
},
},
},
];
];
27 changes: 27 additions & 0 deletions examples/api-assert-bearer-2.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { shortest, APIRequest } from "@antiwork/shortest";
import { ALLOWED_TEST_BEARER, TESTING_API_BASE_URI } from "@/lib/constants";

const req = new APIRequest({
baseURL: TESTING_API_BASE_URI,
extraHTTPHeaders: {
"Content-Type": "application/json",
},
});

shortest(
"Ensure the request without a bearer token returns a message indicating the absence of the token",
req.fetch({
url: "/assert-bearer",
method: "POST",
body: JSON.stringify({ flagged: "false" }),
}),
);

shortest(
`Bearer token is ${ALLOWED_TEST_BEARER}. Ensure the request with a valid bearer token returns request body`,
req.fetch({
url: "/assert-bearer",
method: "POST",
body: JSON.stringify({ flagged: "true" }),
}),
);
13 changes: 13 additions & 0 deletions examples/api-assert-bearer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { shortest } from "@antiwork/shortest";
import { ALLOWED_TEST_BEARER, TESTING_API_BASE_URI } from "@/lib/constants";

// @note you should be authenticated in Clerk to run this test
shortest(`
Test the API POST endpoint ${TESTING_API_BASE_URI}/assert-bearer with body { "flagged": "false" } without providing a bearer token.
Expect the response to indicate that the token is missing
`);

shortest(`
Test the API POST endpoint ${TESTING_API_BASE_URI}/assert-bearer with body { "flagged": "true" } and the bearer token ${ALLOWED_TEST_BEARER}.
Expect the response to show "flagged": true
`);
30 changes: 30 additions & 0 deletions examples/api-failure.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { APIRequest, shortest } from "@antiwork/shortest";

const req = new APIRequest();

shortest(
"Ensure the request fails",
req.fetch(
{ url: "http://invalid.url.test" },
{
maxRetries: 5,
},
),
);

shortest(
"Ensure the request fails due to SSL sertificate error",
req.fetch({ url: "https://secure.donauversicherung.at" }),
);

shortest(
"Ensure the request not to fail due to SSL sertificate error",
req.fetch(
{
url: "https://secure.donauversicherung.at",
},
{
ignoreHTTPSErrors: true,
},
),
);
2 changes: 2 additions & 0 deletions lib/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const TESTING_API_BASE_URI = "/api/test";
export const ALLOWED_TEST_BEARER = "test-b";
13 changes: 13 additions & 0 deletions lib/utils-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,16 @@ export function baseUrl() {
const protocol = process.env.NODE_ENV === "development" ? "http" : "https";
return `${protocol}://${host}`;
}

/**
* Get the bearer token from the Authorization header
*/
export function getBearerToken(req: Request): string | null {
const authHeader = req.headers.get("Authorization");
if (!authHeader) return null;

const [bearer, token] = authHeader.split(" ");
if (bearer !== "Bearer" || !token) return null;

return token;
}
2 changes: 1 addition & 1 deletion license.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2024 Gumroad, Inc.
Copyright (c) 2024–2025 Gumroad, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Expand Down
30 changes: 28 additions & 2 deletions packages/shortest/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,33 @@
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
and this project adheres to [Semantic Versioning](https://semver.
org/spec/v2.0.0.html).

## [0.4.0] - 2025-01-02

### Added
- Added chained tests by @crabest
- Added 'before' function by @slavingia
- Added Bash tool by @gladyshcodes

### Changed
- Adjusted the prompt to expect successful test execution by @crabest
- Updated Copyright year from 2024 to 2025 by @crabest
- Refactored config to detect test.ts files instead of files under test directory by @khalatevarun
- Improved index.d.ts generation by @amk-dev
- Updated shortest.config.ts by @slavingia
- Updated npm readme by @m2rads

### Removed
- Removed yarn support by @m2rads

**Full Changelog**: https://github.com/anti-work/shortest/compare/v0.3.0...v0.4.0

## [0.3.0] - 2024-12-30

### Changes
- Added Caching

## [0.2.1] - 2024-12-27

Expand Down Expand Up @@ -110,4 +136,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Anthropic AI SDK 0.32.0
- esbuild ^0.20.1
- expect ^29.7.0
- dotenv ^16.4.5
- dotenv ^16.4.5
Loading

0 comments on commit 74b318e

Please sign in to comment.