diff --git a/session_test.ts b/session_test.ts
new file mode 100644
index 0000000..05bee3e
--- /dev/null
+++ b/session_test.ts
@@ -0,0 +1,397 @@
+/**
+ * Tests for session.ts.
+ */
+// deno-lint-ignore-file no-import-prefix no-unversioned-import
+import { describe, it } from 'jsr:@std/testing/bdd';
+import { expect } from 'jsr:@std/expect';
+import * as fc from 'npm:fast-check';
+
+import {
+ odd_character_wikitext_string,
+ pathological_wikitext_string,
+ spacing_heavy_wikitext_string,
+ wikiish_string,
+} from './_test_utils/arbitraries.ts';
+import { UNICODE_TEXT_FIXTURES } from './_test_utils/unicode_fixtures.ts';
+import { DiagnosticCode } from './events.ts';
+import { createSession } from './session.ts';
+import { events, outlineEvents, parse, parseWithDiagnostics, parseWithRecovery } from './parse.ts';
+import type { TextSource } from './text_source.ts';
+
+const SESSION_FIXTURES = [
+ [
+ '== Lead ==',
+ `A [[Main Page|home]] link with ''italic'' and '''bold'''.`,
+ '',
+ '* Bullet one',
+ '* Bullet two with {{Card|title=Plan|body=value}}',
+ '',
+ '{|',
+ '! Planet !! Notes',
+ '|-',
+ '| Mars || [Known as the red planet]',
+ '|}',
+ ].join('\n'),
+ [
+ 'Paragraph with [[literal]] text and & entity.',
+ 'Second line keeps the paragraph open until a blank line.',
+ '',
+ '; Term',
+ ': Description with [https://example.com label]',
+ ].join('\n'),
+ [
+ '[[[[{{{{