Add member_for_more_than_three_years account attribute#27
Add member_for_more_than_three_years account attribute#27alltheseas wants to merge 1 commit intodamus-io:masterfrom
Conversation
📝 WalkthroughWalkthroughReworks membership-time computation: introduces a local Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Companion iOS PR: damus-io/damus#3592 — adds the triple star badge UI and parses the |
6b0ae7d to
14155d4
Compare
|
@jb55 for your review, complementary PR to iOS Damus three star PR damus-io/damus#3592 |
Return active_membership_duration (seconds) in the attributes payload so the client can compute badge tiers locally. Keeps member_for_more_than_one_year for backward compat with shipped clients. Signed-off-by: elsat <elsat@protonmail.com> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
14155d4 to
8d16a41
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
test/router_config.test.js (1)
168-169: Missing assertion message stringsLines 168–169 omit descriptive messages, unlike the equivalent assertion at line 147. Consistent messages aid in diagnosing failures.
♻️ Proposed fix
- t.ok(payload.attributes.active_membership_duration > one_year_in_seconds) - t.ok(payload.attributes.active_membership_duration < 3 * one_year_in_seconds) + t.ok(payload.attributes.active_membership_duration > one_year_in_seconds, 'duration should exceed one year') + t.ok(payload.attributes.active_membership_duration < 3 * one_year_in_seconds, 'duration should be less than three years')🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/router_config.test.js` around lines 168 - 169, Add descriptive assertion messages to the two t.ok calls that check payload.attributes.active_membership_duration so failures are easier to diagnose: update the t.ok(payload.attributes.active_membership_duration > one_year_in_seconds) and t.ok(payload.attributes.active_membership_duration < 3 * one_year_in_seconds) calls to include a third argument string (e.g. "active_membership_duration is greater than one year" and "active_membership_duration is less than three years") matching the style used earlier in the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@test/router_config.test.js`:
- Around line 88-98: The test for the account route is missing an assertion for
the new attributes.member_for_more_than_three_years field; update the test in
router_config.test.js (the block using t.equal and res.body.attributes) to
assert that res.body.attributes.member_for_more_than_three_years is false for
this ~30-day legacy account, placing the assertion alongside the existing
member_for_more_than_one_year check so the test verifies both flags.
- Around line 109-193: Add assertions for the new
member_for_more_than_three_years attribute in each sub-test that calls
get_account_info_payload: for the "new account" test assert
payload.attributes.member_for_more_than_three_years === false; for the "> 3
years" test assert payload.attributes.member_for_more_than_three_years === true;
for the "> 1 year but < 3 years" test assert
payload.attributes.member_for_more_than_three_years === false; and for the
"inactive account" test assert
payload.attributes.member_for_more_than_three_years === false (also ensure the
inactive test still checks payload.active and active_membership_duration as
before).
---
Nitpick comments:
In `@test/router_config.test.js`:
- Around line 168-169: Add descriptive assertion messages to the two t.ok calls
that check payload.attributes.active_membership_duration so failures are easier
to diagnose: update the t.ok(payload.attributes.active_membership_duration >
one_year_in_seconds) and t.ok(payload.attributes.active_membership_duration < 3
* one_year_in_seconds) calls to include a third argument string (e.g.
"active_membership_duration is greater than one year" and
"active_membership_duration is less than three years") matching the style used
earlier in the test.
| t.equal(res.body.pubkey, account_info.pubkey) | ||
| t.equal(res.body.created_at, account_info.created_at) | ||
| t.equal(res.body.subscriber_number, 1) | ||
| t.equal(res.body.expiry, account_info.expiry) | ||
| t.equal(res.body.active, true) | ||
| t.equal(res.body.testflight_url, null) | ||
| t.equal(res.body.attributes.member_for_more_than_one_year, false) | ||
| // Legacy account with 30-day past + 30-day future expiry yields ~60 days of membership | ||
| const sixty_days = 60 * 24 * 60 * 60 | ||
| t.ok(res.body.attributes.active_membership_duration > sixty_days - 10, 'duration should be approximately 60 days') | ||
| t.ok(res.body.attributes.active_membership_duration < sixty_days + 10, 'duration should be approximately 60 days') |
There was a problem hiding this comment.
Missing member_for_more_than_three_years assertion in route test
The route test validates member_for_more_than_one_year but never asserts on the new member_for_more_than_three_years field. Since the account is only ~30 days old, the expected value is false.
🐛 Proposed fix
t.equal(res.body.attributes.member_for_more_than_one_year, false)
+ t.equal(res.body.attributes.member_for_more_than_three_years, false)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| t.equal(res.body.pubkey, account_info.pubkey) | |
| t.equal(res.body.created_at, account_info.created_at) | |
| t.equal(res.body.subscriber_number, 1) | |
| t.equal(res.body.expiry, account_info.expiry) | |
| t.equal(res.body.active, true) | |
| t.equal(res.body.testflight_url, null) | |
| t.equal(res.body.attributes.member_for_more_than_one_year, false) | |
| // Legacy account with 30-day past + 30-day future expiry yields ~60 days of membership | |
| const sixty_days = 60 * 24 * 60 * 60 | |
| t.ok(res.body.attributes.active_membership_duration > sixty_days - 10, 'duration should be approximately 60 days') | |
| t.ok(res.body.attributes.active_membership_duration < sixty_days + 10, 'duration should be approximately 60 days') | |
| t.equal(res.body.pubkey, account_info.pubkey) | |
| t.equal(res.body.created_at, account_info.created_at) | |
| t.equal(res.body.subscriber_number, 1) | |
| t.equal(res.body.expiry, account_info.expiry) | |
| t.equal(res.body.active, true) | |
| t.equal(res.body.testflight_url, null) | |
| t.equal(res.body.attributes.member_for_more_than_one_year, false) | |
| t.equal(res.body.attributes.member_for_more_than_three_years, false) | |
| // Legacy account with 30-day past + 30-day future expiry yields ~60 days of membership | |
| const sixty_days = 60 * 24 * 60 * 60 | |
| t.ok(res.body.attributes.active_membership_duration > sixty_days - 10, 'duration should be approximately 60 days') | |
| t.ok(res.body.attributes.active_membership_duration < sixty_days + 10, 'duration should be approximately 60 days') |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@test/router_config.test.js` around lines 88 - 98, The test for the account
route is missing an assertion for the new
attributes.member_for_more_than_three_years field; update the test in
router_config.test.js (the block using t.equal and res.body.attributes) to
assert that res.body.attributes.member_for_more_than_three_years is false for
this ~30-day legacy account, placing the assertion alongside the existing
member_for_more_than_one_year check so the test verifies both flags.
| t.test('new account returns duration and member_for_more_than_one_year false', async (t) => { | ||
| const account = { | ||
| pubkey: 'abc123', | ||
| created_at: current_time() - thirty_days_in_seconds, | ||
| expiry: current_time() + thirty_days_in_seconds, | ||
| transactions: [{ | ||
| type: 'iap', | ||
| id: '1', | ||
| start_date: current_time() - thirty_days_in_seconds, | ||
| end_date: current_time() + thirty_days_in_seconds, | ||
| purchased_date: current_time() - thirty_days_in_seconds, | ||
| duration: null | ||
| }] | ||
| } | ||
| const payload = get_account_info_payload(1, account) | ||
| t.equal(payload.attributes.member_for_more_than_one_year, false) | ||
| t.ok(payload.attributes.active_membership_duration > 0, 'duration should be positive for active account') | ||
| t.ok(payload.attributes.active_membership_duration < one_year_in_seconds, 'duration should be less than one year') | ||
| t.end() | ||
| }) | ||
|
|
||
| t.test('account with > 3 years returns correct duration', async (t) => { | ||
| const total_duration = 3 * one_year_in_seconds + 1 | ||
| const account = { | ||
| pubkey: 'abc123', | ||
| created_at: current_time() - total_duration, | ||
| expiry: current_time() + thirty_days_in_seconds, | ||
| transactions: [{ | ||
| type: 'iap', | ||
| id: '1', | ||
| start_date: current_time() - total_duration, | ||
| end_date: current_time(), | ||
| purchased_date: current_time() - total_duration, | ||
| duration: null | ||
| }] | ||
| } | ||
| const payload = get_account_info_payload(1, account) | ||
| t.equal(payload.attributes.member_for_more_than_one_year, true) | ||
| t.ok(payload.attributes.active_membership_duration > 3 * one_year_in_seconds, 'duration should exceed three years') | ||
| t.end() | ||
| }) | ||
|
|
||
| t.test('account with > 1 year but < 3 years returns correct duration', async (t) => { | ||
| const total_duration = one_year_in_seconds + 1 | ||
| const account = { | ||
| pubkey: 'abc123', | ||
| created_at: current_time() - total_duration, | ||
| expiry: current_time() + thirty_days_in_seconds, | ||
| transactions: [{ | ||
| type: 'iap', | ||
| id: '1', | ||
| start_date: current_time() - total_duration, | ||
| end_date: current_time(), | ||
| purchased_date: current_time() - total_duration, | ||
| duration: null | ||
| }] | ||
| } | ||
| const payload = get_account_info_payload(1, account) | ||
| t.equal(payload.attributes.member_for_more_than_one_year, true) | ||
| t.ok(payload.attributes.active_membership_duration > one_year_in_seconds) | ||
| t.ok(payload.attributes.active_membership_duration < 3 * one_year_in_seconds) | ||
| t.end() | ||
| }) | ||
|
|
||
| t.test('inactive account returns zero duration', async (t) => { | ||
| const total_duration = 3 * one_year_in_seconds + 1 | ||
| const account = { | ||
| pubkey: 'abc123', | ||
| created_at: current_time() - total_duration, | ||
| expiry: current_time() - 1, // expired | ||
| transactions: [{ | ||
| type: 'iap', | ||
| id: '1', | ||
| start_date: current_time() - total_duration, | ||
| end_date: current_time() - 1, | ||
| purchased_date: current_time() - total_duration, | ||
| duration: null | ||
| }] | ||
| } | ||
| const payload = get_account_info_payload(1, account) | ||
| t.equal(payload.active, false) | ||
| t.equal(payload.attributes.member_for_more_than_one_year, false) | ||
| t.equal(payload.attributes.active_membership_duration, 0) | ||
| t.end() | ||
| }) |
There was a problem hiding this comment.
New test suite never asserts on member_for_more_than_three_years — the primary attribute added by this PR
All four sub-tests check member_for_more_than_one_year and active_membership_duration but completely omit the member_for_more_than_three_years attribute. This contradicts the stated test plan ("Verify accounts with > 1080 days return member_for_more_than_three_years: true", "Verify inactive accounts return false for both attributes").
Expected assertions per sub-test:
| Test case | member_for_more_than_three_years |
|---|---|
| New account (30 days) | false |
| > 3 years | true |
| > 1 year but < 3 years | false |
| Inactive | false |
🐛 Proposed additions
// new account test (~line 124)
t.equal(payload.attributes.member_for_more_than_one_year, false)
+ t.equal(payload.attributes.member_for_more_than_three_years, false)
// > 3 years test (~line 146)
t.equal(payload.attributes.member_for_more_than_one_year, true)
+ t.equal(payload.attributes.member_for_more_than_three_years, true)
// > 1 year but < 3 years test (~line 167)
t.equal(payload.attributes.member_for_more_than_one_year, true)
+ t.equal(payload.attributes.member_for_more_than_three_years, false)
// inactive account test (~line 190)
t.equal(payload.attributes.member_for_more_than_one_year, false)
+ t.equal(payload.attributes.member_for_more_than_three_years, false)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@test/router_config.test.js` around lines 109 - 193, Add assertions for the
new member_for_more_than_three_years attribute in each sub-test that calls
get_account_info_payload: for the "new account" test assert
payload.attributes.member_for_more_than_three_years === false; for the "> 3
years" test assert payload.attributes.member_for_more_than_three_years === true;
for the "> 1 year but < 3 years" test assert
payload.attributes.member_for_more_than_three_years === false; and for the
"inactive account" test assert
payload.attributes.member_for_more_than_three_years === false (also ensure the
inactive test still checks payload.active and active_membership_duration as
before).
Summary
member_for_more_than_three_yearsboolean to the account attributes responsetotal_membership_timeonce and reuse for both thresholdsLine count breakdown
6 lines implementation, 92 lines test
Companion PR
iOS client: damus-io/damus#3592
Test plan
router_config.test.jsto expect the new fieldmember_for_more_than_three_years: falsemember_for_more_than_three_years: truefalsefor both attributes🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes