diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,13 @@
 
 `pandoc-lua-marshal` uses [PVP Versioning][].
 
+## 0.3.2.1
+
+Released 2026-01-09.
+
+  * Added missing entry `test/test-table.lua` to
+    *extra-source-files* in cabal file.
+
 ## 0.3.2
 
 Released 2026-01-08.
diff --git a/pandoc-lua-marshal.cabal b/pandoc-lua-marshal.cabal
--- a/pandoc-lua-marshal.cabal
+++ b/pandoc-lua-marshal.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.4
 name:                pandoc-lua-marshal
-version:             0.3.2
+version:             0.3.2.1
 synopsis:            Use pandoc types in Lua
 description:         This package provides functions to marshal and unmarshal
                      pandoc document types to and from Lua.
@@ -37,6 +37,7 @@
                    , test/test-metavalue.lua
                    , test/test-pandoc.lua
                    , test/test-simpletable.lua
+                   , test/test-table.lua
 
 source-repository head
   type:                git
diff --git a/test/test-table.lua b/test/test-table.lua
new file mode 100644
--- /dev/null
+++ b/test/test-table.lua
@@ -0,0 +1,77 @@
+local tasty = require 'tasty'
+
+local test = tasty.test_case
+local group = tasty.test_group
+local assert = tasty.assert
+
+return {
+  group "TableBody" {
+    group 'Constructor' {
+      test('row_head_columns defaults to 0', function ()
+        local tbl_body = TableBody{}
+        assert.are_equal(tbl_body.row_head_columns, 0)
+      end),
+      test('attr defaults to null Attr', function ()
+        local tbl_body = TableBody{}
+        assert.are_equal(tbl_body.attr, Attr())
+      end),
+      test('Table constructor', function ()
+        local old_body = {
+          attr={ 'tbl-body' },
+          body={ Row{ Cell('body cell') } },
+          head={ Row{ Cell('head cell') } },
+          row_head_columns=1
+        }
+        local old_tbl = Table({}, {}, TableHead(), { old_body }, TableFoot())
+
+        local new_body = TableBody(
+          { Row{ Cell('body cell') } },
+          { Row{ Cell('head cell') } },
+          1,
+          { 'tbl-body' }
+        )
+        local new_tbl = Table({}, {}, TableHead(), { new_body }, TableFoot())
+        assert.are_equal(old_tbl, new_tbl)
+      end),
+    },
+    group 'properties' {
+      test('modify body', function ()
+        local tbl_body = TableBody{}
+        tbl_body.body = { Row{ Cell('pass') } }
+        assert.are_equal(TableBody({ Row{ Cell('pass') } }, {}, 0), tbl_body)
+      end),
+      test('modify head', function ()
+        local tbl_body = TableBody{}
+        tbl_body.head = { Row{ Cell('pass') } }
+        assert.are_equal(TableBody({}, { Row{ Cell('pass') } }, 0), tbl_body)
+      end),
+      test('modify row_head_columns', function ()
+        local tbl_body = TableBody{}
+        tbl_body.row_head_columns = 5
+        assert.are_equal(TableBody({}, {}, 5), tbl_body)
+      end),
+      test('modify attr', function ()
+        local tbl_body = TableBody({}, {}, 0, Attr('before'))
+        tbl_body.attr = Attr('after')
+        assert.are_equal(TableBody({}, {}, 0, Attr('after')), tbl_body)
+      end),
+    },
+    group 'aliases' {
+      test('identifier', function ()
+        local tbl_body = TableBody{}
+        tbl_body.identifier = 'yep'
+        assert.are_same(TableBody({}, {}, 0, 'yep'), tbl_body)
+      end),
+      test('classes', function ()
+        local tbl_body = TableBody{}
+        tbl_body.classes = {'java'}
+        assert.are_same(TableBody({}, {}, 0, {'', {'java'}}), tbl_body)
+      end),
+      test('attributes', function ()
+        local tbl_body = TableBody{}
+        tbl_body.attributes.precipitation = 'snow'
+        assert.are_same(TableBody({}, {}, 0, {precipitation='snow'}), tbl_body)
+      end),
+    },
+  },
+}
