fixtures: give the household a family to compose into
Two birthday cards were playing house with nothing in common,
no surname between them, just a group id they were given.
Three Booles move in carrying no address of their own,
so the only street they show is the one the household loans.

Assisted-by: Claude Opus 5 via Claude Code
change xnmsuykmwttwruzztmsrpxrulrttykzo
commit 5c7caef2173932465c60edd75e05a3dd104abd2c
author Alpha Chen <alpha@kejadlen.dev>
date
parent oyozqrqu
diff --git a/test/fixture_data.rb b/test/fixture_data.rb
index 4ec5f24..ee1c27a 100644
--- a/test/fixture_data.rb
+++ b/test/fixture_data.rb
@@ -19,7 +19,7 @@ module FixtureData
 
   # The first card is stamped now and each one after it is #SPREAD times
   # older than the last, so the seed book runs from this minute out to
-  # about five months at sixteen cards. Computed rather than tabulated
+  # about five years at nineteen cards. Computed rather than tabulated
   # because a table runs out: adding cards past the end of one either
   # wraps — two cards sharing a stamp, and a recently-updated list that
   # opens on a tie — or leaves the tail unstamped. Spread rather than
@@ -47,23 +47,30 @@ module FixtureData
     "TEL;TYPE=home:+44 20 5555 0100",
   ].freeze #: Array[String]
 
-  # The groups the fixture book carries: one household, two members.
+  # The groups the fixture book carries: one household, the three
+  # household-* cards in it. Those cards are a family — one surname, a
+  # mobile and an email each, and no address or home number of their
+  # own — so the only home address the admin UI shows on them is the
+  # one this group composes in, and removing a member visibly takes it
+  # away. They sit outside the recorded macOS exchange's hrefs, so the
+  # replay keeps serving that session the bytes it saw.
+  #
   # Seeded in Ruby rather than a fixture file because the cards are the
   # only evidence-shaped fixtures — a group is rows across three
-  # tables with no file format of its own — and the members are chosen
-  # to sit outside the recorded macOS exchange's hrefs, so the replay
-  # keeps serving that session the bytes it saw. Authoring groups is
-  # the admin UI's task; until it arrives nothing public writes these
+  # tables with no file format of its own. Authoring groups is the
+  # admin UI's task; until it arrives nothing public writes these
   # tables, so the rows land the way backdate's do, through the
   # store's own database.
+  MEMBERS = %w[household-george household-mary household-alicia].freeze #: Array[String]
+
   #: (ProTacts::Store store) -> void
   def self.seed_groups(store)
     database = store.instance_variable_get(:@database)
-    database[:groups].insert(id: "household", name: "Household")
+    database[:groups].insert(id: "household", name: "Boole household")
     HOUSEHOLD.each.with_index do |line, position|
       database[:group_properties].insert(group_id: "household", position:, line:)
     end
-    ["bday-complete", "bday-basic-noyear"].each do |id|
+    MEMBERS.each do |id|
       database[:group_members].insert(group_id: "household", card_id: id)
     end
   end
diff --git a/test/fixtures/cards/household-alicia.vcf b/test/fixtures/cards/household-alicia.vcf
new file mode 100644
index 0000000..791bf6f
--- /dev/null
+++ b/test/fixtures/cards/household-alicia.vcf
@@ -0,0 +1,9 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Boole;Alicia;;;
+FN:Alicia Boole
+EMAIL:alicia@example.com
+TEL;TYPE=cell:+44 7700 900103
+BDAY:1860-06-08
+UID:household-alicia
+END:VCARD
diff --git a/test/fixtures/cards/household-george.vcf b/test/fixtures/cards/household-george.vcf
new file mode 100644
index 0000000..c385494
--- /dev/null
+++ b/test/fixtures/cards/household-george.vcf
@@ -0,0 +1,9 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Boole;George;;;
+FN:George Boole
+EMAIL:george@example.com
+TEL;TYPE=cell:+44 7700 900101
+BDAY:1815-11-02
+UID:household-george
+END:VCARD
diff --git a/test/fixtures/cards/household-mary.vcf b/test/fixtures/cards/household-mary.vcf
new file mode 100644
index 0000000..782624e
--- /dev/null
+++ b/test/fixtures/cards/household-mary.vcf
@@ -0,0 +1,10 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Boole;Mary;Everest;;
+FN:Mary Everest Boole
+NICKNAME:Mrs B
+EMAIL:mary@example.com
+TEL;TYPE=cell:+44 7700 900102
+BDAY:1832-03-11
+UID:household-mary
+END:VCARD
diff --git a/test/fixtures/macos-exchange/05-propfind-addressbook-ctag/response b/test/fixtures/macos-exchange/05-propfind-addressbook-ctag/response
index e760787..83fa64b 100644
--- a/test/fixtures/macos-exchange/05-propfind-addressbook-ctag/response
+++ b/test/fixtures/macos-exchange/05-propfind-addressbook-ctag/response
@@ -16,8 +16,8 @@ Content-Type: text/xml
           <d:report><d:sync-collection/></d:report>
         </d:supported-report>
       </d:supported-report-set>
-      <cs:getctag>16</cs:getctag>
-      <d:sync-token>http://pro-tacts/sync/16</d:sync-token>
+      <cs:getctag>19</cs:getctag>
+      <d:sync-token>http://pro-tacts/sync/19</d:sync-token>
       <d:current-user-privilege-set>
         <d:privilege><d:read/></d:privilege>
         <d:privilege><d:write/></d:privilege>
diff --git a/test/fixtures/macos-exchange/06-propfind-addressbook-listing/response b/test/fixtures/macos-exchange/06-propfind-addressbook-listing/response
index 5913f18..816ca3a 100644
--- a/test/fixtures/macos-exchange/06-propfind-addressbook-listing/response
+++ b/test/fixtures/macos-exchange/06-propfind-addressbook-listing/response
@@ -26,7 +26,7 @@ Content-Type: text/xml
   <d:href>/dav/addressbook/bday-basic-noyear.vcf</d:href>
   <d:propstat>
     <d:prop>
-      <d:getetag>"78822ddd3e94790ad8132d452c65b9a9214b695f5db650b1882081696f04b080"</d:getetag>
+      <d:getetag>"bbc86afedab3b3dfa349da2ff6ed736922389a68074fc7a7905b40b1825bc425"</d:getetag>
     </d:prop>
     <d:status>HTTP/1.1 200 OK</d:status>
   </d:propstat>
@@ -35,7 +35,7 @@ Content-Type: text/xml
   <d:href>/dav/addressbook/bday-complete.vcf</d:href>
   <d:propstat>
     <d:prop>
-      <d:getetag>"ea55ff3f6cf660799cbc5b25f86d9e219e7c5b57aecb2a86f4c0af8687805861"</d:getetag>
+      <d:getetag>"4f18a47439816f1488e1bea6ddd31b26dd098de0e5245e57e70e32944be12804"</d:getetag>
     </d:prop>
     <d:status>HTTP/1.1 200 OK</d:status>
   </d:propstat>
@@ -112,6 +112,33 @@ Content-Type: text/xml
     <d:status>HTTP/1.1 200 OK</d:status>
   </d:propstat>
 </d:response>
+<d:response>
+  <d:href>/dav/addressbook/household-alicia.vcf</d:href>
+  <d:propstat>
+    <d:prop>
+      <d:getetag>"6c01a910f23f1cad35baec49312f787d0cb4c324f3b4cdd9b826536b87c8445a"</d:getetag>
+    </d:prop>
+    <d:status>HTTP/1.1 200 OK</d:status>
+  </d:propstat>
+</d:response>
+<d:response>
+  <d:href>/dav/addressbook/household-george.vcf</d:href>
+  <d:propstat>
+    <d:prop>
+      <d:getetag>"2dcd92c33d147687f4a669a2b3f4dba19bb9f6a093ebc990a054926294864091"</d:getetag>
+    </d:prop>
+    <d:status>HTTP/1.1 200 OK</d:status>
+  </d:propstat>
+</d:response>
+<d:response>
+  <d:href>/dav/addressbook/household-mary.vcf</d:href>
+  <d:propstat>
+    <d:prop>
+      <d:getetag>"d6c544cb829cbf1be3fbbd8e2b47b752c4e4659c45c4d233613b543b9db6517f"</d:getetag>
+    </d:prop>
+    <d:status>HTTP/1.1 200 OK</d:status>
+  </d:propstat>
+</d:response>
 <d:response>
   <d:href>/dav/addressbook/memoji.vcf</d:href>
   <d:propstat>
diff --git a/test/fixtures/macos-exchange/08-report-sync-collection/response b/test/fixtures/macos-exchange/08-report-sync-collection/response
index c8d226e..cf250bb 100644
--- a/test/fixtures/macos-exchange/08-report-sync-collection/response
+++ b/test/fixtures/macos-exchange/08-report-sync-collection/response
@@ -16,7 +16,7 @@ Content-Type: text/xml
   <d:href>/dav/addressbook/bday-basic-noyear.vcf</d:href>
   <d:propstat>
     <d:prop>
-      <d:getetag>"78822ddd3e94790ad8132d452c65b9a9214b695f5db650b1882081696f04b080"</d:getetag>
+      <d:getetag>"bbc86afedab3b3dfa349da2ff6ed736922389a68074fc7a7905b40b1825bc425"</d:getetag>
     </d:prop>
     <d:status>HTTP/1.1 200 OK</d:status>
   </d:propstat>
@@ -25,7 +25,7 @@ Content-Type: text/xml
   <d:href>/dav/addressbook/bday-complete.vcf</d:href>
   <d:propstat>
     <d:prop>
-      <d:getetag>"ea55ff3f6cf660799cbc5b25f86d9e219e7c5b57aecb2a86f4c0af8687805861"</d:getetag>
+      <d:getetag>"4f18a47439816f1488e1bea6ddd31b26dd098de0e5245e57e70e32944be12804"</d:getetag>
     </d:prop>
     <d:status>HTTP/1.1 200 OK</d:status>
   </d:propstat>
@@ -102,6 +102,33 @@ Content-Type: text/xml
     <d:status>HTTP/1.1 200 OK</d:status>
   </d:propstat>
 </d:response>
+<d:response>
+  <d:href>/dav/addressbook/household-alicia.vcf</d:href>
+  <d:propstat>
+    <d:prop>
+      <d:getetag>"6c01a910f23f1cad35baec49312f787d0cb4c324f3b4cdd9b826536b87c8445a"</d:getetag>
+    </d:prop>
+    <d:status>HTTP/1.1 200 OK</d:status>
+  </d:propstat>
+</d:response>
+<d:response>
+  <d:href>/dav/addressbook/household-george.vcf</d:href>
+  <d:propstat>
+    <d:prop>
+      <d:getetag>"2dcd92c33d147687f4a669a2b3f4dba19bb9f6a093ebc990a054926294864091"</d:getetag>
+    </d:prop>
+    <d:status>HTTP/1.1 200 OK</d:status>
+  </d:propstat>
+</d:response>
+<d:response>
+  <d:href>/dav/addressbook/household-mary.vcf</d:href>
+  <d:propstat>
+    <d:prop>
+      <d:getetag>"d6c544cb829cbf1be3fbbd8e2b47b752c4e4659c45c4d233613b543b9db6517f"</d:getetag>
+    </d:prop>
+    <d:status>HTTP/1.1 200 OK</d:status>
+  </d:propstat>
+</d:response>
 <d:response>
   <d:href>/dav/addressbook/memoji.vcf</d:href>
   <d:propstat>
@@ -138,6 +165,6 @@ Content-Type: text/xml
     <d:status>HTTP/1.1 200 OK</d:status>
   </d:propstat>
 </d:response>
-  <d:sync-token>http://pro-tacts/sync/16</d:sync-token>
+  <d:sync-token>http://pro-tacts/sync/19</d:sync-token>
 
 </d:multistatus>
diff --git a/test/fixtures/macos-exchange/09-propfind-addressbook-bootstrap/response b/test/fixtures/macos-exchange/09-propfind-addressbook-bootstrap/response
index 36affd2..9e740d2 100644
--- a/test/fixtures/macos-exchange/09-propfind-addressbook-bootstrap/response
+++ b/test/fixtures/macos-exchange/09-propfind-addressbook-bootstrap/response
@@ -16,8 +16,8 @@ Content-Type: text/xml
           <d:report><d:sync-collection/></d:report>
         </d:supported-report>
       </d:supported-report-set>
-      <cs:getctag>16</cs:getctag>
-      <d:sync-token>http://pro-tacts/sync/16</d:sync-token>
+      <cs:getctag>19</cs:getctag>
+      <d:sync-token>http://pro-tacts/sync/19</d:sync-token>
       <d:current-user-privilege-set>
         <d:privilege><d:read/></d:privilege>
         <d:privilege><d:write/></d:privilege>
@@ -51,7 +51,7 @@ Content-Type: text/xml
   <d:href>/dav/addressbook/bday-basic-noyear.vcf</d:href>
   <d:propstat>
     <d:prop>
-      <d:getetag>"78822ddd3e94790ad8132d452c65b9a9214b695f5db650b1882081696f04b080"</d:getetag>
+      <d:getetag>"bbc86afedab3b3dfa349da2ff6ed736922389a68074fc7a7905b40b1825bc425"</d:getetag>
     </d:prop>
     <d:status>HTTP/1.1 200 OK</d:status>
   </d:propstat>
@@ -60,7 +60,7 @@ Content-Type: text/xml
   <d:href>/dav/addressbook/bday-complete.vcf</d:href>
   <d:propstat>
     <d:prop>
-      <d:getetag>"ea55ff3f6cf660799cbc5b25f86d9e219e7c5b57aecb2a86f4c0af8687805861"</d:getetag>
+      <d:getetag>"4f18a47439816f1488e1bea6ddd31b26dd098de0e5245e57e70e32944be12804"</d:getetag>
     </d:prop>
     <d:status>HTTP/1.1 200 OK</d:status>
   </d:propstat>
@@ -137,6 +137,33 @@ Content-Type: text/xml
     <d:status>HTTP/1.1 200 OK</d:status>
   </d:propstat>
 </d:response>
+<d:response>
+  <d:href>/dav/addressbook/household-alicia.vcf</d:href>
+  <d:propstat>
+    <d:prop>
+      <d:getetag>"6c01a910f23f1cad35baec49312f787d0cb4c324f3b4cdd9b826536b87c8445a"</d:getetag>
+    </d:prop>
+    <d:status>HTTP/1.1 200 OK</d:status>
+  </d:propstat>
+</d:response>
+<d:response>
+  <d:href>/dav/addressbook/household-george.vcf</d:href>
+  <d:propstat>
+    <d:prop>
+      <d:getetag>"2dcd92c33d147687f4a669a2b3f4dba19bb9f6a093ebc990a054926294864091"</d:getetag>
+    </d:prop>
+    <d:status>HTTP/1.1 200 OK</d:status>
+  </d:propstat>
+</d:response>
+<d:response>
+  <d:href>/dav/addressbook/household-mary.vcf</d:href>
+  <d:propstat>
+    <d:prop>
+      <d:getetag>"d6c544cb829cbf1be3fbbd8e2b47b752c4e4659c45c4d233613b543b9db6517f"</d:getetag>
+    </d:prop>
+    <d:status>HTTP/1.1 200 OK</d:status>
+  </d:propstat>
+</d:response>
 <d:response>
   <d:href>/dav/addressbook/memoji.vcf</d:href>
   <d:propstat>