diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2778c83 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "WP Env", + "type": "php", + "request": "launch", + "port": 9003, + "pathMappings": { + "/var/www/html/wp-content/plugins/wordpress": "${workspaceFolder}/" + } + } + ] +} \ No newline at end of file diff --git a/tests/cypress/e2e/submission/unsubscribe.test.js b/tests/cypress/e2e/submission/unsubscribe.test.js index a8e3e4a..885b336 100644 --- a/tests/cypress/e2e/submission/unsubscribe.test.js +++ b/tests/cypress/e2e/submission/unsubscribe.test.js @@ -17,10 +17,11 @@ describe('Unsubscribe form', () => { cy.selectList('10up'); // Ensure list is selected, refreshes Mailchimp data with WP + // Single Opt-in + cy.setDoubleOptInOption(false); + // Check unsubscription link - cy.visit('/wp-admin/admin.php?page=mailchimp_sf_options'); - cy.get('#mc_use_unsub_link').check(); - cy.get('input[value="Update Subscribe Form Settings"]').first().click(); + cy.setSettingsOption('#mc_use_unsub_link', true); }); after(() => { @@ -28,9 +29,17 @@ describe('Unsubscribe form', () => { cy.login(); // WP // Uncheck unsubscription link - cy.visit('/wp-admin/admin.php?page=mailchimp_sf_options'); - cy.get('#mc_use_unsub_link').uncheck(); - cy.get('input[value="Update Subscribe Form Settings"]').first().click(); + cy.setSettingsOption('#mc_use_unsub_link', false); + }); + + it('unsubscribe link appears on both shortcode and block pages', () => { + [shortcodePostURL, blockPostPostURL].forEach((url) => { + // Visit the mailchimp block page + cy.visit(url); + + // Assert unsubscribe link exists + cy.get('a[href*="/unsubscribe"]').should('exist'); + }); }) it('unsubscribes valid emails that were previously subscribed to a list', () => { @@ -41,81 +50,90 @@ describe('Unsubscribe form', () => { cy.subscribeToList(listId, email); }); - [shortcodePostURL, blockPostPostURL].forEach((url) => { - let baseUrl; + let baseUrl; - // Visit the mailchimp block page - cy.visit(url); + // Visit the mailchimp block page + cy.visit(blockPostPostURL); - // Get baseUrl to use for later assertion - cy.url().then((url) => { - // Extract the base URL - const urlObject = new URL(url); - baseUrl = `${urlObject.protocol}//${urlObject.host}`; - }); - + // Get baseUrl to use for later assertion + cy.url().then((url) => { + // Extract the base URL + const urlObject = new URL(url); + baseUrl = `${urlObject.protocol}//${urlObject.host}`; + }); - // Assert unsubscribe link exists - cy.get('a[href*="/unsubscribe"]').should('exist'); - // Visit unsubscribe link - cy.get('a[href*="/unsubscribe"]') - .invoke('removeAttr', 'target') // Prevent opening in new window so that Cypress can test - .click(); + // Assert unsubscribe link exists + cy.get('a[href*="/unsubscribe"]').should('exist'); - // Unsubscribe - cy.get('#email-address').type(email); - cy.get('input[type="submit"]').click(); - cy.get('body').should('contain', 'Unsubscribe Successful'); + // Visit unsubscribe link + cy.get('a[href*="/unsubscribe"]') + .invoke('removeAttr', 'target') // Prevent opening in new window so that Cypress can test + .click(); - // Navigate back to the website button exists - cy.contains('a', 'return to our website') - .should('exist'); + // Unsubscribe + cy.get('#email-address').type(email); + cy.get('input[type="submit"]').click(); + cy.get('body').should('contain', 'Unsubscribe Successful'); + + // Navigate back to the website button exists + cy.contains('a', 'return to our website') + .should('exist'); + + // Verify contact exists in Mailchimp with status 'unsubscribed' + cy.verifyContactInMailchimp(email, '10up', 'unsubscribed').then((contact) => { + cy.verifyContactStatus(contact, 'unsubscribed'); // Delete contact to clean up cy.deleteContactFromList(email); - - // Navigate to website - // NOTE: The website URL is site in Mailchimp and it won't accept localhost or our test URL - // TODO: Assert that we're back on our website (we currently have no way to set this) - // cy.contains('a', 'return to our website').click(); - // cy.url().should('include', baseUrl); // TODO: Do we want to assert a specific landing page? - }); + + // Navigate to back website + // NOTE: The website URL is site in Mailchimp and it won't accept localhost or our test URL + // TODO: Assert that we're back on our website (we currently have no way to set this) + // cy.contains('a', 'return to our website').click(); + // cy.url().should('include', baseUrl); // TODO: Do we want to assert a specific landing page? }); - + it('throws an error when unsubscribing an email that was never subscribed to a list', () => { const email = generateRandomEmail('never-subscribed-user'); - [shortcodePostURL, blockPostPostURL].forEach((url) => { - // Visit the mailchimp block page - cy.visit(url); + // Visit the mailchimp block page + cy.visit(blockPostPostURL); - // Assert unsubscribe link exists - cy.get('a[href*="/unsubscribe"]').should('exist'); + // Assert unsubscribe link exists + cy.get('a[href*="/unsubscribe"]').should('exist'); - // Visit unsubscribe link - cy.get('a[href*="/unsubscribe"]') - .invoke('removeAttr', 'target') // Prevent opening in new window so that Cypress can test - .click(); + // Visit unsubscribe link + cy.get('a[href*="/unsubscribe"]') + .invoke('removeAttr', 'target') // Prevent opening in new window so that Cypress can test + .click(); - // Unsubscribe - cy.get('#email-address').type(email); - cy.get('input[type="submit"]').click(); + // Unsubscribe + cy.get('#email-address').type(email); + cy.get('input[type="submit"]').click(); - // Assert that the unsubscribe didn't work because the email isn't subscribed - cy.get('.errorText').should('contain', 'this email is not subscribed'); - - }); + // Assert that the unsubscribe didn't work because the email isn't subscribed + cy.get('.errorText').should('contain', 'this email is not subscribed'); }); - // TODO: Test not written yet - it.skip('does not display an unsubscribe link when the unsubscribe option is disabled', () => { - // Test here... - }); + it('does not display an unsubscribe link when the unsubscribe option is disabled', () => { + // Not sure why we have to login for this test, but we do + cy.login(); // WP - // TODO: Test not written yet - it.skip('redirects the user back to the website when the user is finished unsubscribing and clicks the back link', () => { - // Test here... + // Uncheck unsubscription link + cy.setSettingsOption('#mc_use_unsub_link', false); + + [shortcodePostURL, blockPostPostURL].forEach((url) => { + // Visit the mailchimp block page + cy.visit(url); + + // Assert unsubscribe link exists + cy.get('a[href*="/unsubscribe"]').should('not.exist'); + }); }); + + // NOTE: We can not set the "return to website" URL from the Mailchimp plugin or through the API. + // Alternative proposals on issue #91 and #92 to add a user tutorial + // it.skip('redirects the user back to the website when the user is finished unsubscribing and clicks the back link', () => {}); }); \ No newline at end of file diff --git a/tests/cypress/support/commands/mailchimpApi.js b/tests/cypress/support/commands/mailchimpApi.js index 8a93c17..6786fd9 100644 --- a/tests/cypress/support/commands/mailchimpApi.js +++ b/tests/cypress/support/commands/mailchimpApi.js @@ -47,9 +47,36 @@ async function getListId(listName) { * Gets lists from the account of the API token set in the mailchimp config */ Cypress.Commands.add('getContactsFromAList', getContactsFromAList); -async function getContactsFromAList(listId) { - const response = await mailchimp.lists.getListMembersInfo(listId); - return response.members; +async function getContactsFromAList(listId, status = null) { + let members = []; + let offset = 0; + const count = 100; // Number of members to fetch per request (Mailchimp's limit is usually 1000 per page) + + while (true) { + const options = { + count, + offset, + }; + + // Add status filter if provided + if (status) { + options.status = status; + } + + const response = await mailchimp.lists.getListMembersInfo(listId, options); + + members = members.concat(response.members); + + // Break the loop if we've fetched all members + if (members.length >= response.total_items) { + break; + } + + // Increment the offset for the next page + offset += count; + } + + return members; } /** @@ -125,7 +152,7 @@ async function updateMergeFieldByTag(listId, tag, data) { async function getMergeFields(listId) { let mergeFields = []; let offset = 0; - const count = 25; // Number of fields to fetch per request + const count = 100; // Number of fields to fetch per request while (true) { const response = await mailchimp.lists.getListMergeFields(listId, { diff --git a/tests/cypress/support/commands/settings.js b/tests/cypress/support/commands/settings.js index 7f5daf9..e2491e3 100644 --- a/tests/cypress/support/commands/settings.js +++ b/tests/cypress/support/commands/settings.js @@ -75,6 +75,17 @@ function setDoubleOptInOption(enabled) { cy.get('input[value="Update Subscribe Form Settings"]').first().click(); } +Cypress.Commands.add('setSettingsOption', setSettingsOption); +function setSettingsOption(selector, enabled) { + cy.visit('/wp-admin/admin.php?page=mailchimp_sf_options'); + if (enabled) { + cy.get(selector).check(); + } else { + cy.get(selector).uncheck(); + } + cy.get('input[value="Update Subscribe Form Settings"]').first().click(); +} + /** * Custom Cypress command to enable or disable Mailchimp merge fields in the WordPress admin settings. * diff --git a/tests/cypress/support/commands/submission.js b/tests/cypress/support/commands/submission.js index 2a902e1..0f79260 100644 --- a/tests/cypress/support/commands/submission.js +++ b/tests/cypress/support/commands/submission.js @@ -23,17 +23,18 @@ Cypress.Commands.add('submitFormAndVerifyError', () => { /** * Custom command to verify that a contact was added to a specified list in Mailchimp */ -Cypress.Commands.add('verifyContactInMailchimp', (email, listName = '10up') => { +Cypress.Commands.add('verifyContactInMailchimp', (email, listName = '10up', status = null) => { // Step 1: Get the list ID for the specified list name cy.getListId(listName).then((listId) => { // Step 2: Retrieve the contacts from the specified list - cy.getContactsFromAList(listId).then((contacts) => { - cy.log('Contacts retrieved:', contacts); // Log the contacts for debugging + cy.getContactsFromAList(listId, status).then((contacts) => { + // Log the contacts for debugging + console.log(contacts) // Step 3: Verify that the contact with the provided email exists in the list const contact = contacts.find((c) => c.email_address === email); expect(contact).to.exist; - return contact; + cy.wrap(contact); // Wrap the contact to allow further chaining }); }); });