diff --git a/test/regression/api/admin/__snapshots__/members.test.js.snap b/test/regression/api/admin/__snapshots__/members.test.js.snap index 9fc642a99b..458c0f9a91 100644 --- a/test/regression/api/admin/__snapshots__/members.test.js.snap +++ b/test/regression/api/admin/__snapshots__/members.test.js.snap @@ -764,6 +764,699 @@ Object { } `; +exports[`Members API Members API with Stripe Add should fail when passing incorrect email_type query parameter 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "249", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Add should fail when passing incorrect email_type query parameter 2: [body] 1`] = ` +Object { + "errors": Array [ + Object { + "code": null, + "context": "Validation (AllowedValues) failed for email_type", + "details": null, + "help": null, + "id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "message": "Validation error, cannot save member.", + "property": null, + "type": "ValidationError", + }, + ], +} +`; + +exports[`Members API Members API with Stripe Can add and send a signup confirmation email 1: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member_getting_confirmation@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Array [], + "name": "Send Me Confirmation", + "note": null, + "products": Array [], + "status": "free", + "subscribed": true, + "subscriptions": Array [], + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], +} +`; + +exports[`Members API Members API with Stripe Can add and send a signup confirmation email 2: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "457", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "location": Any, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Can add and send a signup confirmation email 3: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Can delete a member without cancelling Stripe Subscription 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Can delete a member without cancelling Stripe Subscription 2: [body] 1`] = `Object {}`; + +exports[`Members API Members API with Stripe Can order by email_open_rate 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "7008", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Can order by email_open_rate 2: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "paid@test.com", + "email_count": 0, + "email_open_rate": 80, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Egon Spengler", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member2@test.com", + "email_count": 0, + "email_open_rate": 50, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": null, + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member1@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Mr Egg", + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "trialing@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Ray Stantz", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "comped@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Vinz Clortho", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "vip@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Winston Zeddemore", + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "vip-paid@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Peter Venkman", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "with-product@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Dana Barrett", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 8, + }, + }, +} +`; + +exports[`Members API Members API with Stripe Can order by email_open_rate 3: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "7008", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Can order by email_open_rate 4: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member2@test.com", + "email_count": 0, + "email_open_rate": 50, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": null, + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "paid@test.com", + "email_count": 0, + "email_open_rate": 80, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Egon Spengler", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member1@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Mr Egg", + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "trialing@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Ray Stantz", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "comped@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Vinz Clortho", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "vip@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Winston Zeddemore", + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "vip-paid@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Peter Venkman", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "with-product@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Dana Barrett", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 8, + }, + }, +} +`; + +exports[`Members API Members API with Stripe Can update a member with subscription included, change name to "Updated name" 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "1234", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Can update a member with subscription included, change name to "Updated name" 2: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "paid@test.com", + "email_count": 0, + "email_open_rate": 80, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Updated name", + "note": null, + "products": Array [], + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], +} +`; + +exports[`Members API Members API with Stripe Errors when fetching stats with unknown days param value 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "248", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Errors when fetching stats with unknown days param value 2: [body] 1`] = ` +Object { + "errors": Array [ + Object { + "code": null, + "context": "Validation (matches) failed for id undefined.id", + "details": null, + "help": null, + "id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "message": "Validation error, cannot read member.", + "property": null, + "type": "ValidationError", + }, + ], +} +`; + +exports[`Members API Members API with Stripe Sarch by case-insensitive name egg receives member with name Mr Egg 1: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member1@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Mr Egg", + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 1, + }, + }, +} +`; + +exports[`Members API Members API with Stripe Sarch by case-insensitive name egg receives member with name Mr Egg 2: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "644", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Sarch for paid members retrieves member with email paid@test.com 1: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "paid@test.com", + "email_count": 0, + "email_open_rate": 80, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Egon Spengler", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 1, + }, + }, +} +`; + +exports[`Members API Members API with Stripe Sarch for paid members retrieves member with email paid@test.com 2: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "1296", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Search by case-insensitive email MEMBER2 receives member with email member2@test.com 1: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member2@test.com", + "email_count": 0, + "email_open_rate": 50, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": null, + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 1, + }, + }, +} +`; + +exports[`Members API Members API with Stripe Search by case-insensitive email MEMBER2 receives member with email member2@test.com 2: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "491", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Search for non existing member returns empty result set 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "102", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API Members API with Stripe Search for non existing member returns empty result set 2: [body] 1`] = ` +Object { + "members": Array [], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 0, + }, + }, +} +`; + exports[`Members API Sarch by case-insensitive name egg receives member with name Mr Egg 1: [body] 1`] = ` Object { "members": Array [ @@ -935,3 +1628,765 @@ Object { }, } `; + +exports[`Members API with Stripe Add should fail when passing incorrect email_type query parameter 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "249", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Add should fail when passing incorrect email_type query parameter 2: [body] 1`] = ` +Object { + "errors": Array [ + Object { + "code": null, + "context": "Validation (AllowedValues) failed for email_type", + "details": null, + "help": null, + "id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "message": "Validation error, cannot save member.", + "property": null, + "type": "ValidationError", + }, + ], +} +`; + +exports[`Members API with Stripe Can add and send a signup confirmation email 1: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member_getting_confirmation@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Array [], + "name": "Send Me Confirmation", + "note": null, + "products": Array [], + "status": "free", + "subscribed": true, + "subscriptions": Array [], + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], +} +`; + +exports[`Members API with Stripe Can add and send a signup confirmation email 2: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "457", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "location": Any, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Can add and send a signup confirmation email 3: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Can delete a member without cancelling Stripe Subscription 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "438", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "location": Any, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Can delete a member without cancelling Stripe Subscription 2: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "Member2Delete@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Array [], + "name": "Member 2 Delete", + "note": null, + "products": Array [], + "status": "free", + "subscribed": true, + "subscriptions": Array [], + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], +} +`; + +exports[`Members API with Stripe Can delete a member without cancelling Stripe Subscription 3: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Can delete a member without cancelling Stripe Subscription 4: [body] 1`] = `Object {}`; + +exports[`Members API with Stripe Can order by email_open_rate 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "7008", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Can order by email_open_rate 2: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "paid@test.com", + "email_count": 0, + "email_open_rate": 80, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Egon Spengler", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member2@test.com", + "email_count": 0, + "email_open_rate": 50, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": null, + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member1@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Mr Egg", + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "trialing@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Ray Stantz", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "comped@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Vinz Clortho", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "vip@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Winston Zeddemore", + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "vip-paid@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Peter Venkman", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "with-product@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Dana Barrett", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 8, + }, + }, +} +`; + +exports[`Members API with Stripe Can order by email_open_rate 3: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "7008", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Can order by email_open_rate 4: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member2@test.com", + "email_count": 0, + "email_open_rate": 50, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": null, + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "paid@test.com", + "email_count": 0, + "email_open_rate": 80, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Egon Spengler", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member1@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Mr Egg", + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "trialing@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Ray Stantz", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "comped@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Vinz Clortho", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "vip@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Winston Zeddemore", + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "vip-paid@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Peter Venkman", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "with-product@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Dana Barrett", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 8, + }, + }, +} +`; + +exports[`Members API with Stripe Can update a member with subscription included, change name to "Updated name" 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "1234", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Can update a member with subscription included, change name to "Updated name" 2: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "paid@test.com", + "email_count": 0, + "email_open_rate": 80, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Updated name", + "note": null, + "products": Array [], + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], +} +`; + +exports[`Members API with Stripe Errors when fetching stats with unknown days param value 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "248", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Errors when fetching stats with unknown days param value 2: [body] 1`] = ` +Object { + "errors": Array [ + Object { + "code": null, + "context": "Validation (matches) failed for id undefined.id", + "details": null, + "help": null, + "id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "message": "Validation error, cannot read member.", + "property": null, + "type": "ValidationError", + }, + ], +} +`; + +exports[`Members API with Stripe Sarch by case-insensitive name egg receives member with name Mr Egg 1: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member1@test.com", + "email_count": 0, + "email_open_rate": null, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Mr Egg", + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 1, + }, + }, +} +`; + +exports[`Members API with Stripe Sarch by case-insensitive name egg receives member with name Mr Egg 2: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "644", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Sarch for paid members retrieves member with email paid@test.com 1: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "paid@test.com", + "email_count": 0, + "email_open_rate": 80, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": "Egon Spengler", + "note": null, + "status": "paid", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 1, + }, + }, +} +`; + +exports[`Members API with Stripe Sarch for paid members retrieves member with email paid@test.com 2: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "1296", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Search by case-insensitive email MEMBER2 receives member with email member2@test.com 1: [body] 1`] = ` +Object { + "members": Array [ + Object { + "avatar_image": null, + "comped": false, + "created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "email": "member2@test.com", + "email_count": 0, + "email_open_rate": 50, + "email_opened_count": 0, + "geolocation": null, + "id": StringMatching /\\[a-f0-9\\]\\{24\\}/, + "labels": Any, + "name": null, + "note": null, + "status": "free", + "subscribed": true, + "subscriptions": Any, + "updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/, + "uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + }, + ], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 1, + }, + }, +} +`; + +exports[`Members API with Stripe Search by case-insensitive email MEMBER2 receives member with email member2@test.com 2: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "491", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Search for non existing member returns empty result set 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "102", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API with Stripe Search for non existing member returns empty result set 2: [body] 1`] = ` +Object { + "members": Array [], + "meta": Object { + "pagination": Object { + "limit": 15, + "next": null, + "page": 1, + "pages": 1, + "prev": null, + "total": 0, + }, + }, +} +`; + +exports[`Members API without Stripe Add should fail when comped flag is passed in but Stripe is not enabled 1: [headers] 1`] = ` +Object { + "access-control-allow-origin": "http://127.0.0.1:2369", + "cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0", + "content-length": "376", + "content-type": "application/json; charset=utf-8", + "etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/, + "vary": "Origin, Accept-Encoding", + "x-powered-by": "Express", +} +`; + +exports[`Members API without Stripe Add should fail when comped flag is passed in but Stripe is not enabled 2: [body] 1`] = ` +Object { + "errors": Array [ + Object { + "code": null, + "context": "Missing Stripe connection. Attempting to import members with Stripe data when there is no Stripe account connected.", + "details": null, + "help": "You need to connect to Stripe to import Stripe customers. ", + "id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/, + "message": "Validation error, cannot save member.", + "property": "comped", + "type": "ValidationError", + }, + ], +} +`; diff --git a/test/regression/api/admin/members.test.js b/test/regression/api/admin/members.test.js index 1ed4fa6bf8..c9dd91f623 100644 --- a/test/regression/api/admin/members.test.js +++ b/test/regression/api/admin/members.test.js @@ -1,4 +1,5 @@ const assert = require('assert'); +const nock = require('nock'); const {agentProvider, mockManager, fixtureManager, matchers} = require('../../../utils/e2e-framework'); const {anyString, anyArray, anyObjectId, anyEtag, anyUuid, anyErrorId, anyDate} = matchers; @@ -21,242 +22,263 @@ const memberMatcherShallowIncludes = { }; describe('Members API', function () { - before(async function () { - agent = await agentProvider.getAdminAPIAgent(); - await fixtureManager.init('members'); - await agent.loginAsOwner(); - }); - - beforeEach(function () { - mockManager.mockLabsEnabled('members'); - mockManager.mockMail(); - }); - - afterEach(function () { - mockManager.restore(); - }); - - it('Can add and send a signup confirmation email', async function () { - const member = { - name: 'Send Me Confirmation', - email: 'member_getting_confirmation@test.com', - subscribed: true - }; - - const queryParams = { - send_email: true, - email_type: 'signup' - }; - - const {body} = await agent - .post('/members/?send_email=true&email_type=signup') - .body({members: [member]}) - .expectStatus(201) - .matchBodySnapshot({ - members: [memberMatcherNoIncludes] - }) - .matchHeaderSnapshot({ - etag: anyEtag, - location: anyString - }); - - mockManager.assert.sentEmail({ - subject: '🙌 Complete your sign up to Ghost!', - to: 'member_getting_confirmation@test.com' + describe('without Stripe', function () { + before(async function () { + agent = await agentProvider.getAdminAPIAgent(); + await fixtureManager.init('members'); + await agent.loginAsOwner(); }); - // @TODO: do we really need to delete this member here? - await agent - .delete(`members/${body.members[0].id}/`) - .matchHeaderSnapshot({ - etag: anyEtag - }) - .expectStatus(204); + beforeEach(function () { + mockManager.mockLabsEnabled('members'); + mockManager.mockMail(); + }); + + afterEach(function () { + mockManager.restore(); + }); + + it('Add should fail when comped flag is passed in but Stripe is not enabled', async function () { + const newMember = { + email: 'memberTestAdd@test.com', + comped: true + }; + + await agent + .post(`members/`) + .body({members: [newMember]}) + .expectStatus(422) + .matchHeaderSnapshot({ + etag: anyEtag + }) + .matchBodySnapshot({ + errors: [{ + id: anyErrorId + }] + }); + }); }); - it('Can order by email_open_rate', async function () { - await agent - .get('members/?order=email_open_rate%20desc') - .expectStatus(200) - .matchHeaderSnapshot({ - etag: anyEtag - }) - .matchBodySnapshot({ - members: new Array(8).fill(memberMatcherShallowIncludes) - }) - .expect(({body}) => { - const {members} = body; - assert.equal(members[0].email_open_rate > members[1].email_open_rate, true, 'Expected the first member to have a greater open rate than the second.'); + describe('Members API with Stripe', function () { + before(async function () { + mockManager.setupStripe(); + agent = await agentProvider.getAdminAPIAgent(); + await fixtureManager.init('members'); + await agent.loginAsOwner(); + }); + + beforeEach(function () { + mockManager.mockLabsEnabled('members'); + mockManager.mockMail(); + mockManager.mockStripe(); + }); + + afterEach(function () { + mockManager.restore(); + }); + + it('Can add and send a signup confirmation email', async function () { + const member = { + name: 'Send Me Confirmation', + email: 'member_getting_confirmation@test.com', + subscribed: true + }; + + const queryParams = { + send_email: true, + email_type: 'signup' + }; + + const {body} = await agent + .post('/members/?send_email=true&email_type=signup') + .body({members: [member]}) + .expectStatus(201) + .matchBodySnapshot({ + members: [memberMatcherNoIncludes] + }) + .matchHeaderSnapshot({ + etag: anyEtag, + location: anyString + }); + + mockManager.assert.sentEmail({ + subject: '🙌 Complete your sign up to Ghost!', + to: 'member_getting_confirmation@test.com' }); - await agent - .get('members/?order=email_open_rate%20asc') - .expectStatus(200) - .matchHeaderSnapshot({ - etag: anyEtag - }) - .matchBodySnapshot({ - members: new Array(8).fill(memberMatcherShallowIncludes) - }) - .expect(({body}) => { - const {members} = body; - assert.equal(members[0].email_open_rate < members[1].email_open_rate, true, 'Expected the first member to have a smaller open rate than the second.'); - }); - }); + // @TODO: do we really need to delete this member here? + await agent + .delete(`members/${body.members[0].id}/`) + .matchHeaderSnapshot({ + etag: anyEtag + }) + .expectStatus(204); + }); - it('Sarch by case-insensitive name egg receives member with name Mr Egg', async function () { - await agent - .get('members/?search=egg') - .expectStatus(200) - .matchBodySnapshot({ - members: [memberMatcherShallowIncludes] - }) - .matchHeaderSnapshot({ - etag: anyEtag - }); - }); + it('Can order by email_open_rate', async function () { + await agent + .get('members/?order=email_open_rate%20desc') + .expectStatus(200) + .matchHeaderSnapshot({ + etag: anyEtag + }) + .matchBodySnapshot({ + members: new Array(8).fill(memberMatcherShallowIncludes) + }) + .expect(({body}) => { + const {members} = body; + assert.equal(members[0].email_open_rate > members[1].email_open_rate, true, 'Expected the first member to have a greater open rate than the second.'); + }); - it('Search by case-insensitive email MEMBER2 receives member with email member2@test.com', async function () { - await agent - .get('members/?search=MEMBER2') - .expectStatus(200) - .matchBodySnapshot({ - members: [memberMatcherShallowIncludes] - }) - .matchHeaderSnapshot({ - etag: anyEtag - }); - }); + await agent + .get('members/?order=email_open_rate%20asc') + .expectStatus(200) + .matchHeaderSnapshot({ + etag: anyEtag + }) + .matchBodySnapshot({ + members: new Array(8).fill(memberMatcherShallowIncludes) + }) + .expect(({body}) => { + const {members} = body; + assert.equal(members[0].email_open_rate < members[1].email_open_rate, true, 'Expected the first member to have a smaller open rate than the second.'); + }); + }); - it('Sarch for paid members retrieves member with email paid@test.com', async function () { - await agent - .get('members/?search=egon&paid=true') - .expectStatus(200) - .matchBodySnapshot({ - members: [memberMatcherShallowIncludes] - }) - .matchHeaderSnapshot({ - etag: anyEtag - }); - }); + it('Sarch by case-insensitive name egg receives member with name Mr Egg', async function () { + await agent + .get('members/?search=egg') + .expectStatus(200) + .matchBodySnapshot({ + members: [memberMatcherShallowIncludes] + }) + .matchHeaderSnapshot({ + etag: anyEtag + }); + }); - it('Search for non existing member returns empty result set', async function () { - await agent - .get('members/?search=do_not_exist') - .expectStatus(200) - .matchHeaderSnapshot({ - etag: anyEtag - }) - .matchBodySnapshot({ - members: [] - }); - }); + it('Search by case-insensitive email MEMBER2 receives member with email member2@test.com', async function () { + await agent + .get('members/?search=MEMBER2') + .expectStatus(200) + .matchBodySnapshot({ + members: [memberMatcherShallowIncludes] + }) + .matchHeaderSnapshot({ + etag: anyEtag + }); + }); - it('Can update a member with subscription included, change name to "Updated name"', async function () { - const memberChanged = { - name: 'Updated name' - }; + it('Sarch for paid members retrieves member with email paid@test.com', async function () { + await agent + .get('members/?search=egon&paid=true') + .expectStatus(200) + .matchBodySnapshot({ + members: [memberMatcherShallowIncludes] + }) + .matchHeaderSnapshot({ + etag: anyEtag + }); + }); - const paidMember = fixtureManager.get('members', 2); + it('Search for non existing member returns empty result set', async function () { + await agent + .get('members/?search=do_not_exist') + .expectStatus(200) + .matchHeaderSnapshot({ + etag: anyEtag + }) + .matchBodySnapshot({ + members: [] + }); + }); - await agent - .put(`members/${paidMember.id}/`) - .body({members: [memberChanged]}) - .expectStatus(200) - .matchHeaderSnapshot({ - etag: anyEtag - }) - .matchBodySnapshot({ - members: [memberMatcherShallowIncludes] - }); - }); + it('Can update a member with subscription included, change name to "Updated name"', async function () { + const memberChanged = { + name: 'Updated name' + }; - it('Add should fail when passing incorrect email_type query parameter', async function () { - const newMember = { - name: 'test', - email: 'memberTestAdd@test.com' - }; + const paidMember = fixtureManager.get('members', 2); - await agent - .post(`members/?send_email=true&email_type=lel`) - .body({members: [newMember]}) - .expectStatus(422) - .matchHeaderSnapshot({ - etag: anyEtag - }) - .matchBodySnapshot({ - errors: [{ - id: anyErrorId - }] - }); - }); + await agent + .put(`members/${paidMember.id}/`) + .body({members: [memberChanged]}) + .expectStatus(200) + .matchHeaderSnapshot({ + etag: anyEtag + }) + .matchBodySnapshot({ + members: [memberMatcherShallowIncludes] + }); + }); - it('Add should fail when comped flag is passed in but Stripe is not enabled', async function () { - const newMember = { - email: 'memberTestAdd@test.com', - comped: true - }; + it('Add should fail when passing incorrect email_type query parameter', async function () { + const newMember = { + name: 'test', + email: 'memberTestAdd@test.com' + }; - await agent - .post(`members/`) - .body({members: [newMember]}) - .expectStatus(422) - .matchHeaderSnapshot({ - etag: anyEtag - }) - .matchBodySnapshot({ - errors: [{ - id: anyErrorId - }] - }); - }); + await agent + .post(`members/?send_email=true&email_type=lel`) + .body({members: [newMember]}) + .expectStatus(422) + .matchHeaderSnapshot({ + etag: anyEtag + }) + .matchBodySnapshot({ + errors: [{ + id: anyErrorId + }] + }); + }); - it('Can delete a member without cancelling Stripe Subscription', async function () { - const newMember = { - name: 'Member 2 Delete', - email: 'Member2Delete@test.com' - }; + it('Can delete a member without cancelling Stripe Subscription', async function () { + let subscriptionCanceled = false; + nock('https://api.stripe.com') + .persist() + .delete(/v1\/.*/) + .reply((uri) => { + const [match, resource, id] = uri.match(/\/?v1\/(\w+)\/?(\w+)/) || [null]; - // @TODO: use a fixture member in the right state using fixtureManager.get('members', x) - // @TODO: instead of creating a new member as this wastes a request - const createdMember = await agent - .post(`members/`) - .body({members: [newMember]}) - .expectStatus(201) - .matchHeaderSnapshot({ - etag: anyEtag, - location: anyString - }) - .matchBodySnapshot({ - members: [ - memberMatcherNoIncludes - ] - }) - .then(({body}) => { - return body.members[0]; - }); + if (match && resource === 'subscriptions') { + subscriptionCanceled = true; + return [200, { + id, + status: 'canceled' + }]; + } - await agent - .delete(`members/${createdMember.id}/`) - .expectStatus(204) - .matchHeaderSnapshot({ - etag: anyEtag - }) - .matchBodySnapshot(); - // @TODO: assert side effect - stripe subscription is not cancelled - }); + return [500]; + }); - it('Errors when fetching stats with unknown days param value', async function () { - await agent - .get('members/stats/?days=nope') - .expectStatus(422) - .matchHeaderSnapshot({ - etag: anyEtag - }) - .matchBodySnapshot({ - errors: [{ - id: anyErrorId - }] - }); + // TODO This is wrong because it changes the state for teh rest of the tests + // We need to add a member via a fixture and then remove them OR work out how + // to reapply fixtures before each test + const memberToDelete = fixtureManager.get('members', 2); + + await agent + .delete(`members/${memberToDelete.id}/`) + .expectStatus(204) + .matchHeaderSnapshot({ + etag: anyEtag + }) + .matchBodySnapshot(); + + assert.equal(subscriptionCanceled, false, 'expected subscription not to be canceled'); + }); + + it('Errors when fetching stats with unknown days param value', async function () { + await agent + .get('members/stats/?days=nope') + .expectStatus(422) + .matchHeaderSnapshot({ + etag: anyEtag + }) + .matchBodySnapshot({ + errors: [{ + id: anyErrorId + }] + }); + }); }); });