Skip to content

Add Cypress tests for contact form functionality#71

Open
alikon wants to merge 6 commits into
mainfrom
cypress-test-4customreply
Open

Add Cypress tests for contact form functionality#71
alikon wants to merge 6 commits into
mainfrom
cypress-test-4customreply

Conversation

@alikon

@alikon alikon commented Jun 1, 2026

Copy link
Copy Markdown
Owner

This test suite verifies the functionality of the contact form, including creating a contact and sending an email upon submission.

Summary by Sourcery

Add frontend contact form Cypress coverage and wire the contact custom reply plugin to the user factory for email handling.

New Features:

  • Add Cypress tests to verify creating a contact via the frontend contact form.
  • Add Cypress tests to verify email sending on contact form submission, with and without the custom reply feature enabled.

Enhancements:

  • Inject the UserFactory into the contact custom reply plugin via the service provider and UserFactoryAwareTrait to support user-aware behaviour.

Tests:

  • Extend existing MagicLogin Cypress test to clear emails before running and add a new Cypress suite covering contact form creation and email notifications.

This test suite verifies the functionality of the contact form, including creating a contact and sending an email upon submission.
@sourcery-ai

sourcery-ai Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds Cypress end-to-end coverage for the Joomla contact form, including contact creation and email delivery (with and without the CustomReply plugin), and wires the CustomReply plugin into the user factory for testability while ensuring email-related tests clear the mail state first.

Sequence diagram for CustomReply plugin wiring with UserFactory

sequenceDiagram
    participant Container
    participant CustomReplyProvider
    participant CustomReply

    Container->>CustomReplyProvider: get PluginInterface
    CustomReplyProvider->>CustomReply: __construct subject config
    CustomReplyProvider->>CustomReply: setApplication
    CustomReplyProvider->>Container: get DatabaseDriver
    CustomReplyProvider->>CustomReply: setDatabase
    CustomReplyProvider->>Container: get UserFactoryInterface
    CustomReplyProvider->>CustomReply: setUserFactory
Loading

File-Level Changes

Change Details Files
Wire the contact custom reply plugin to the Joomla user factory for dependency injection.
  • Import UserFactoryInterface in the contact custom reply service provider.
  • Inject the UserFactory service into the CustomReply plugin instance when it is constructed from the container.
  • Use UserFactoryAwareTrait in the CustomReply plugin class to receive the injected user factory.
src/plugins/contact/customreply/services/provider.php
src/plugins/contact/customreply/src/Extension/CustomReply.php
Ensure email-related Cypress tests start from a clean mail state.
  • Clear pending emails before running the magic login email test so assertions are not affected by previous test runs.
  • Clear pending emails at the beginning of each contact email test scenario.
tests/cypress/integration/plugins/MagicLogin.cy.js
tests/cypress/integration/plugins/ContactCustomReply.cy.js
Add Cypress end-to-end coverage for contact creation and contact-form-triggered emails with and without custom reply enabled.
  • Create a test that logs into the frontend, submits the contact creation form, and verifies the new contact appears in the appropriate category view via a direct DB lookup of the created contact.
  • Create a test that submits a contact form for an existing contact and asserts that an email is sent containing the submitted message body using the test email task helpers.
  • Create a variant of the email test that first enables the custom reply configuration and plugin, then verifies that email delivery still occurs and contains the submitted message content.
tests/cypress/integration/plugins/ContactCustomReply.cy.js

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@alikon alikon marked this pull request as ready for review June 3, 2026 13:10

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 3 issues, and left some high level feedback:

  • The two email submission tests duplicate the same sequence of visiting the contact page and filling/submitting the form; consider extracting a shared helper (e.g. submitContactForm({ name, email, subject, message })) to make the tests shorter and easier to maintain.
  • The test that enables the plg_contact_customreply plugin and updates custom_reply does not reset these settings afterward, which could leak state into other tests; consider reverting these configuration changes in an afterEach or using a dedicated DB reset step for extension settings.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The two email submission tests duplicate the same sequence of visiting the contact page and filling/submitting the form; consider extracting a shared helper (e.g. `submitContactForm({ name, email, subject, message })`) to make the tests shorter and easier to maintain.
- The test that enables the `plg_contact_customreply` plugin and updates `custom_reply` does not reset these settings afterward, which could leak state into other tests; consider reverting these configuration changes in an `afterEach` or using a dedicated DB reset step for extension settings.

## Individual Comments

### Comment 1
<location path="tests/cypress/integration/plugins/ContactCustomReply.cy.js" line_range="26-31" />
<code_context>
+    });
+  });
+
+  it('can send an email on contact form submission', () => {
+    cy.task('clearEmails');
+    cy.db_getUserId().then((id) => cy.db_createContact({ name: 'test contact', user_id: id }))
+      .then((contact) => {
+        cy.visit(`/index.php?option=com_contact&view=contact&id=${contact.id}`);
+        cy.get('#jform_contact_name').type('Test User');
+        cy.get('#jform_contact_email').type('testuser@example.com');
+        cy.get('#jform_contact_emailmsg').type('Test Subject');
+        cy.get('#jform_contact_message').type('Test message content');
+        cy.get('button.btn.btn-primary.validate[type="submit"]').click();
+
+        cy.task('getMails').then((mails) => {
+          expect(mails.length).to.be.greaterThan(0);
+          cy.wrap(mails[0].body).should('contain', 'Test message content');
</code_context>
<issue_to_address>
**suggestion (testing):** Strengthen assertions on the outgoing email (count, recipient, subject) to better prove the behavior.

Right now the test only checks that at least one email is sent and that the first email body contains the message text. Please also assert the exact number of emails, that the recipient matches the configured contact address, and that the subject matches (or includes) the submitted `Test Subject`. These checks will better guard against regressions in email routing or templating.

```suggestion
        cy.get('button.btn.btn-primary.validate[type="submit"]').click();

        cy.task('getMails').then((mails) => {
          expect(mails).to.have.length(1);

          const mail = mails[0];

          if (contact.email_to) {
            expect(mail.to).to.contain(contact.email_to);
          }

          expect(mail.subject).to.contain('Test Subject');
          expect(mail.body).to.contain('Test message content');
        });
```
</issue_to_address>

### Comment 2
<location path="tests/cypress/integration/plugins/ContactCustomReply.cy.js" line_range="35-28" />
<code_context>
+      });
+  });
+
+  it('can send an email on contact form submission with custom reply enabled', () => {
+    cy.task('clearEmails');
+    cy.db_updateExtensionParameter('custom_reply', '1', 'com_contact');
+    cy.db_enableExtension('1', 'plg_contact_customreply');
+    cy.db_getUserId().then((id) => cy.db_createContact({ name: 'test contact', user_id: id }))
+      .then((contact) => {
+        cy.visit(`/index.php?option=com_contact&view=contact&id=${contact.id}`);
+        cy.get('#jform_contact_name').type('Test User');
+        cy.get('#jform_contact_email').type('testuser@example.com');
+        cy.get('#jform_contact_emailmsg').type('Test Subject');
+        cy.get('#jform_contact_message').type('Test message content');
+        cy.get('button.btn.btn-primary.validate[type="submit"]').click();
+
+        cy.task('getMails').then((mails) => {
+          expect(mails.length).to.be.greaterThan(0);
+          cy.wrap(mails[0].body).should('contain', 'Test message content');
</code_context>
<issue_to_address>
**issue (testing):** Differentiate the custom reply test from the non-custom case by asserting plugin-specific behavior.

This mostly duplicates the `can send an email on contact form submission` test, just with the plugin enabled. To validate the custom reply behavior, please add at least one assertion that’s specific to the plugin, such as:
- Expecting an extra email (e.g., admin + auto-reply).
- Verifying one email is sent to `testuser@example.com`.
- Checking for text or a marker introduced by the custom reply plugin.
Otherwise, the test can still pass even if the custom reply logic is broken, as long as the base contact email works.
</issue_to_address>

### Comment 3
<location path="tests/cypress/integration/plugins/ContactCustomReply.cy.js" line_range="25-26" />
<code_context>
+        cy.get('#jform_contact_name').type('Test User');
+        cy.get('#jform_contact_email').type('testuser@example.com');
+        cy.get('#jform_contact_emailmsg').type('Test Subject');
+        cy.get('#jform_contact_message').type('Test message content');
+        cy.get('button.btn.btn-primary.validate[type="submit"]').click();
+
+        cy.task('getMails').then((mails) => {
</code_context>
<issue_to_address>
**suggestion (testing):** Consider asserting on the UI success state after form submission, not only on the email side effect.

These tests only assert on the resulting emails, not on the frontend behavior (success message, lack of validation errors, redirect, etc.). Please add a UI assertion (for example, `cy.contains('Thank you for your message')` or a selector-based check) to verify the user-facing flow and better protect against regressions where the email is sent but the UI fails.

Suggested implementation:

```javascript
        cy.get('#jform_contact_message').type('Test message content');
        cy.get('button.btn.btn-primary.validate[type="submit"]').click();

        // Assert on the UI success state to verify the user-facing flow
        cy.contains('Thank you for your message').should('be.visible');

        cy.task('getMails').then((mails) => {

```

1. If the actual success message text in your Joomla setup differs from `'Thank you for your message'`, update the string in `cy.contains(...)` to match the real UI copy.
2. Alternatively, if there's a stable success-alert selector (e.g. `.alert-success`), you can tighten the assertion to something like:
   `cy.get('.alert-success').should('contain', 'Thank you for your message');`
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +26 to +31
cy.get('button.btn.btn-primary.validate[type="submit"]').click();

cy.task('getMails').then((mails) => {
expect(mails.length).to.be.greaterThan(0);
cy.wrap(mails[0].body).should('contain', 'Test message content');
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Strengthen assertions on the outgoing email (count, recipient, subject) to better prove the behavior.

Right now the test only checks that at least one email is sent and that the first email body contains the message text. Please also assert the exact number of emails, that the recipient matches the configured contact address, and that the subject matches (or includes) the submitted Test Subject. These checks will better guard against regressions in email routing or templating.

Suggested change
cy.get('button.btn.btn-primary.validate[type="submit"]').click();
cy.task('getMails').then((mails) => {
expect(mails.length).to.be.greaterThan(0);
cy.wrap(mails[0].body).should('contain', 'Test message content');
});
cy.get('button.btn.btn-primary.validate[type="submit"]').click();
cy.task('getMails').then((mails) => {
expect(mails).to.have.length(1);
const mail = mails[0];
if (contact.email_to) {
expect(mail.to).to.contain(contact.email_to);
}
expect(mail.subject).to.contain('Test Subject');
expect(mail.body).to.contain('Test message content');
});

cy.get('#jform_contact_message').type('Test message content');
cy.get('button.btn.btn-primary.validate[type="submit"]').click();

cy.task('getMails').then((mails) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (testing): Differentiate the custom reply test from the non-custom case by asserting plugin-specific behavior.

This mostly duplicates the can send an email on contact form submission test, just with the plugin enabled. To validate the custom reply behavior, please add at least one assertion that’s specific to the plugin, such as:

  • Expecting an extra email (e.g., admin + auto-reply).
  • Verifying one email is sent to testuser@example.com.
  • Checking for text or a marker introduced by the custom reply plugin.
    Otherwise, the test can still pass even if the custom reply logic is broken, as long as the base contact email works.

Comment on lines +25 to +26
cy.get('#jform_contact_message').type('Test message content');
cy.get('button.btn.btn-primary.validate[type="submit"]').click();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Consider asserting on the UI success state after form submission, not only on the email side effect.

These tests only assert on the resulting emails, not on the frontend behavior (success message, lack of validation errors, redirect, etc.). Please add a UI assertion (for example, cy.contains('Thank you for your message') or a selector-based check) to verify the user-facing flow and better protect against regressions where the email is sent but the UI fails.

Suggested implementation:

        cy.get('#jform_contact_message').type('Test message content');
        cy.get('button.btn.btn-primary.validate[type="submit"]').click();

        // Assert on the UI success state to verify the user-facing flow
        cy.contains('Thank you for your message').should('be.visible');

        cy.task('getMails').then((mails) => {
  1. If the actual success message text in your Joomla setup differs from 'Thank you for your message', update the string in cy.contains(...) to match the real UI copy.
  2. Alternatively, if there's a stable success-alert selector (e.g. .alert-success), you can tighten the assertion to something like:
    cy.get('.alert-success').should('contain', 'Thank you for your message');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant