Skip to content

Commit c58736e

Browse files
Jonas Saabelclaude
andcommitted
docs: complete Search API and Testing documentation
Complete documentation for Search API with comprehensive examples, limitations, and best practices. Add focused Testing guide explaining test organization and the NOTION_RUN_INTEGRATION_TESTS master switch. Standardize integration test tags across all 26 test files for consistency. All tests now properly tagged with @tags("Integration", "RequiresApi") and appropriate "Slow" tags where needed. Documentation changes: - docs/search.md: Complete guide with 7 example categories, DSL reference, limitations, gotchas, and best practices - docs/testing.md: Focused guide on test organization, master switch, MockResponseBuilder patterns, and warnings - Explain why SearchExamples.kt doesn't exist (workspace-dependent) Test standardization: - Add @tags to 21 integration test files - Update 4 "Slow" tests to include Integration/RequiresApi tags - Add missing import statements to 10 files - All 481 unit tests passing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 7aea65b commit c58736e

24 files changed

+866
-92
lines changed

docs/search.md

Lines changed: 331 additions & 37 deletions
Large diffs are not rendered by default.

docs/testing.md

Lines changed: 152 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,206 @@
1-
# Testing Your Notion Integrations
2-
3-
> **⚠️ WORK IN PROGRESS**: This documentation is being actively developed and may be incomplete or subject to change.
1+
# Testing Guide
42

53
## Overview
64

7-
This guide covers strategies for testing code that uses the Kotlin Notion Client, including how the library's own tests are structured.
5+
This guide explains how the Kotlin Notion Client organizes its tests and how to run them. The library has comprehensive test coverage with fast unit tests and real API integration tests.
6+
7+
## Test Organization
8+
9+
### Unit Tests (`src/test/kotlin/unit/`)
10+
- **Fast**: ~481 tests run in ~200ms
11+
- **No API calls**: Use mock responses from official Notion API samples
12+
- **Tagged**: `@Tags("Unit")`
813

9-
## How This Library Handles Tests
14+
### Integration Tests (`src/test/kotlin/integration/`)
15+
- **Real API**: Make actual requests to Notion
16+
- **Require setup**: Need environment variables
17+
- **Tagged**: `@Tags("Integration", "RequiresApi")` or with `"Slow"` for long-running tests
18+
- **Protected**: Won't run without `NOTION_RUN_INTEGRATION_TESTS=true`
1019

11-
This library uses a unified test approach where integration tests are controlled by environment variables:
20+
### Example Tests (`src/test/kotlin/examples/`)
21+
- **Documentation examples**: Validate code in docs actually works
22+
- **Also integration tests**: Tagged with `@Tags("Integration", "RequiresApi", "Examples")`
23+
24+
## The Master Switch
25+
26+
All integration tests check this environment variable:
1227

1328
```kotlin
14-
// Integration tests check env vars and skip if not set
15-
if (!integrationTestEnvVarsAreSet()) {
16-
"!(Skipped) Integration test" {
17-
println("⏭️ Skipping - missing environment variables")
29+
// From src/test/kotlin/integration/Util.kt
30+
fun integrationTestEnvVarsAreSet(...): Boolean {
31+
if (System.getenv("NOTION_RUN_INTEGRATION_TESTS")?.lowercase() != "true") {
32+
return false // Integration tests skip
1833
}
19-
} else {
20-
// actual test code
34+
// ... check other required env vars
2135
}
2236
```
2337

24-
### Running Tests
38+
**This is your safety**: Integration tests never run without explicit opt-in via environment variable.
39+
40+
## Running Tests
41+
42+
### Fast development (recommended)
2543

2644
```bash
27-
# Run unit tests only (integration tests automatically skip)
45+
# Run only unit tests - fast, no API calls
2846
./gradlew test
2947

30-
# Run with integration tests enabled
48+
# All ~481 unit tests pass in ~200ms
49+
```
50+
51+
### Running specific integration tests
52+
53+
```bash
54+
# Set up once per session
3155
export NOTION_RUN_INTEGRATION_TESTS=true
32-
export NOTION_API_TOKEN="secret_..."
33-
export NOTION_TEST_PAGE_ID="page-id"
56+
export NOTION_API_TOKEN="secret_your_token"
57+
export NOTION_TEST_PAGE_ID="your-page-id"
58+
59+
# Run one integration test
60+
./gradlew test --tests "*PagesIntegrationTest"
61+
```
3462

35-
# Run specific integration test (recommended)
36-
./gradlew test --tests "*SearchIntegrationTest"
63+
### ⚠️ Running ALL integration tests (not recommended)
3764

38-
# ⚠️ Avoid running ALL integration tests at once
39-
# This will perform many real operations on your workspace
65+
```bash
66+
# WARNING: Creates/modifies/deletes real data, takes 5-10+ minutes
67+
export NOTION_RUN_INTEGRATION_TESTS=true
68+
./gradlew testAll
4069
```
4170

42-
### Environment Variables
71+
## Environment Variables
4372

44-
- **`NOTION_RUN_INTEGRATION_TESTS`**: Must be `"true"` to enable integration tests
45-
- **`NOTION_API_TOKEN`**: Your Notion integration API token
46-
- **`NOTION_TEST_PAGE_ID`**: A test page ID where the integration has permissions
47-
- **`NOTION_CLEANUP_AFTER_TEST`**: Set to `"false"` to keep test data (default: cleanup enabled)
73+
| Variable | Purpose | Required For |
74+
|----------|---------|--------------|
75+
| `NOTION_RUN_INTEGRATION_TESTS` | Must be `"true"` to enable integration tests | Integration tests |
76+
| `NOTION_API_TOKEN` | Your integration secret token | Integration tests |
77+
| `NOTION_TEST_PAGE_ID` | A page where integration has permissions | Most integration tests |
78+
| `NOTION_CLEANUP_AFTER_TEST` | Set to `"false"` to keep test data | Optional (default: true) |
4879

49-
## Testing Your Own Code
80+
## Test Infrastructure
81+
82+
### Official API Samples
83+
84+
**File**: `src/test/kotlin/unit/util/TestFixtures.kt`
85+
86+
Unit tests use real responses from Notion's API documentation:
87+
88+
```kotlin
89+
// Load official sample responses
90+
val pageJson = TestFixtures.Pages.retrievePage()
91+
val page: Page = TestFixtures.Pages.retrievePage().decode()
92+
```
93+
94+
### Mock Client Builder
95+
96+
**File**: `src/test/kotlin/unit/util/MockResponseBuilder.kt`
5097

51-
### Unit Testing with Mocks
98+
Create mock HTTP clients for unit tests:
5299

53-
_TODO: Add mocking examples showing how to test code that uses NotionClient_
100+
```kotlin
101+
val mockClient = mockClient {
102+
addPageRetrieveResponse() // Uses official API sample
103+
addDatabaseCreateResponse()
104+
}
105+
106+
val notion = NotionClient.createWithClient(mockClient, NotionConfig(apiToken = "test"))
107+
```
108+
109+
Available mock responses: `addPageRetrieveResponse()`, `addPageCreateResponse()`, `addDatabaseRetrieveResponse()`, `addBlockRetrieveResponse()`, `addSearchResponse()`, and more - see `MockResponseBuilder.kt` for complete list.
110+
111+
## Testing Your Own Code
112+
113+
### With mock responses (unit test)
54114

55115
```kotlin
56-
// Example using mock client (to be added)
57-
class MyNotionServiceTest : FunSpec({
58-
test("should create task page") {
59-
// TODO: Add complete example
116+
import io.kotest.core.spec.style.FunSpec
117+
import unit.util.mockClient
118+
119+
class MyServiceTest : FunSpec({
120+
test("should create page") {
121+
val mockClient = mockClient {
122+
addPageCreateResponse()
123+
}
124+
125+
val notion = NotionClient.createWithClient(mockClient, NotionConfig(apiToken = "test"))
126+
val service = MyService(notion)
127+
128+
val page = service.createTaskPage("Buy groceries")
129+
page.id shouldNotBe null
60130
}
61131
})
62132
```
63133

64-
### Integration Testing Pattern
65-
66-
You can use the same pattern this library uses:
134+
### With real API (integration test)
67135

68136
```kotlin
137+
import io.kotest.core.annotation.Tags
69138
import io.kotest.core.spec.style.StringSpec
70139
import integration.integrationTestEnvVarsAreSet
140+
import integration.shouldCleanupAfterTest
141+
142+
@Tags("Integration", "RequiresApi")
143+
class MyServiceIntegrationTest : StringSpec({
71144

72-
class MyIntegrationTest : StringSpec({
73145
if (!integrationTestEnvVarsAreSet()) {
74-
"!(Skipped) My integration test" {
75-
println("⏭️ Skipping - set NOTION_RUN_INTEGRATION_TESTS=true")
146+
"!(Skipped)" {
147+
println("⏭️ Set NOTION_RUN_INTEGRATION_TESTS=true to run")
76148
}
77149
} else {
78-
val client = NotionClient.create(System.getenv("NOTION_API_TOKEN"))
150+
val notion = NotionClient.create(System.getenv("NOTION_API_TOKEN"))
151+
152+
"should create and retrieve task" {
153+
val task = MyService(notion).createTask("Test task")
154+
155+
task shouldNotBe null
156+
157+
if (shouldCleanupAfterTest()) {
158+
notion.pages.archive(task.id)
159+
}
160+
}
79161

80-
"my test case" {
81-
// Your test code here
162+
afterSpec {
163+
notion.close()
82164
}
83165
}
84166
})
85167
```
86168

87-
### Test Data Management
169+
## Important Warnings
88170

89-
_TODO: Add guidance on managing test data in Notion workspace_
171+
### ❌ DON'T run all integration tests at once
90172

91-
## Common Patterns
173+
Integration tests create/modify/delete real content in your workspace. Run them individually during development.
92174

93-
_TODO: Add tips, gotchas, best practices_
175+
### ❌ DON'T test against production workspaces
94176

95-
### Testing Pagination
177+
Always use a dedicated test workspace or test page. Set `NOTION_TEST_PAGE_ID` to a page specifically for testing.
96178

97-
_TODO: Add pagination testing examples_
179+
### ❌ DON'T commit secrets
98180

99-
### Testing Error Scenarios
181+
Never hardcode API tokens in test files. Always use environment variables.
100182

101-
_TODO: Add error scenario testing examples_
183+
## Tag System
184+
185+
Tests are organized with Kotest tags:
186+
187+
| Tag | Meaning |
188+
|-----|---------|
189+
| `Unit` | Fast mock-based tests |
190+
| `Integration` + `RequiresApi` | Tests that use real Notion API |
191+
| `Slow` | Tests that take >30 seconds (also tagged Integration) |
192+
| `Examples` | Documentation example tests |
193+
194+
Run tests by tag:
195+
```bash
196+
# Only unit tests
197+
./gradlew test -Dkotest.tags.include="Unit"
198+
199+
# Exclude slow tests
200+
./gradlew test -Dkotest.tags.exclude="Slow"
201+
```
102202

103203
## Related Topics
104204

105-
- [Error Handling](error-handling.md) - Understanding errors to test for
205+
- **[Error Handling](error-handling.md)** - Testing error scenarios
206+
- **[CLAUDE.md](/CLAUDE.md)** - Development workflow and test commands

0 commit comments

Comments
 (0)