Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added URL input handling on CTA Card #1417

Merged
merged 3 commits into from
Jan 23, 2025
Merged

Added URL input handling on CTA Card #1417

merged 3 commits into from
Jan 23, 2025

Conversation

ronaldlangeveld
Copy link
Member

@ronaldlangeveld ronaldlangeveld commented Jan 23, 2025

ref https://linear.app/ghost/issue/PLG-313/implement-button-url-update

  • Added URL Input handling for the new CTA Card
  • Allows URL input or selecting from a populated list
  • Added additional test to ensure the button persists in the UI when
    conditions are met, which are whether the URL field is populated, Text
    is populated and the button is active.
  • Improved a test in the button card (not related to the CTA card).

Summary by CodeRabbit

  • New Features

    • Enhanced Call To Action (CTA) card functionality with improved button URL handling.
    • Added dynamic URL updates for CTA card buttons.
  • Tests

    • Expanded test coverage for CTA card interactions.
    • Added tests for button URL setting, suggested URLs, and editing behavior.
    • Improved reliability of suggested URL tests in button card functionality.

ref https://linear.app/ghost/issue/PLG-313/implement-button-url-update

- Added URL Input handling for the new CTA Card
- Allows URL input or selecting from a populated list
- Added additional test to ensure the button persists in the UI when
  conditions are met, which are whether the URL field is populated, Text
is populated and the button is active.
Copy link

coderabbitai bot commented Jan 23, 2025

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/koenig-lexical/test/e2e/cards/button-card.test.js

Oops! Something went wrong! :(

ESLint: 8.57.0

ESLint couldn't find the config "react-app" to extend from. Please check that the name of the config is correct.

The config "react-app" was referenced from the config file in "/packages/koenig-lexical/.eslintrc.cjs".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

Walkthrough

The pull request introduces enhancements to the Call To Action (CTA) card functionality in the Koenig Lexical editor. The changes focus on improving button URL handling, adding a data attribute for testing, and implementing a new method to dynamically update the button URL. Modifications were made to the component implementation and end-to-end testing, with new test cases verifying the button URL setting, suggestion, and interaction behaviors.

Changes

File Change Summary
packages/koenig-lexical/src/components/ui/cards/CtaCard.jsx Added data-test-cta-button-current-url attribute to button wrapper
packages/koenig-lexical/src/nodes/CallToActionNodeComponent.jsx Introduced handleButtonUrlChange method to update button URL dynamically; updated updateButtonUrl prop in CtaCard
packages/koenig-lexical/test/e2e/cards/cta-card.test.js Added three new test cases: URL setting, URL suggestions, and button interaction verification
packages/koenig-lexical/test/e2e/cards/button-card.test.js Modified test for suggested URLs to improve input handling and timing

Sequence Diagram

sequenceDiagram
    participant User
    participant CtaCard
    participant CallToActionNode
    User->>CtaCard: Enter/Update Button URL
    CtaCard->>CallToActionNode: updateButtonUrl(newUrl)
    CallToActionNode-->>CtaCard: URL Updated
    CtaCard->>CtaCard: Render Button with New URL
Loading

Possibly related PRs

Poem

🐰 A rabbit's tale of buttons bright,
URLs dancing with testing might,
Lexical magic, smooth and clean,
Where code and creativity convene,
Hop, hop, hooray for UI delight! 🚀

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ronaldlangeveld ronaldlangeveld marked this pull request as ready for review January 23, 2025 07:40
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/koenig-lexical/test/e2e/cards/cta-card.test.js (2)

67-75: Consider adding edge cases to URL validation test.

While the basic URL setting test is good, consider adding test cases for:

  • Invalid URLs
  • Empty URLs
  • URLs with special characters

102-129: Improve test structure for better readability.

The test covers multiple scenarios but could be more clearly structured. Consider breaking it into distinct sections:

  1. Setup (button settings, text, URL)
  2. Focus management
  3. State verification
 test('button doesnt disappear when toggled, has text, has url and loses focus', async function () {
+    // Setup
     await focusEditor(page);
     await insertCard(page, {cardName: 'call-to-action'});
     await page.click('[data-testid="button-settings"]');
     await page.fill('[data-testid="button-text"]', 'Click me');
     await page.fill('[data-testid="button-url"]', 'https://example.com/somepost');
 
+    // Initial state verification
     expect(await page.isVisible('[data-testid="cta-button"]')).toBe(true);
     expect(await page.textContent('[data-testid="cta-button"]')).toBe('Click me');
     const buttonContainer = await page.$('[data-test-cta-button-current-url]');
     const currentUrl = await buttonContainer.getAttribute('data-test-cta-button-current-url');
     expect(currentUrl).toBe('https://example.com/somepost');

+    // Focus management
     await page.keyboard.press('Escape');
     await page.keyboard.press('Enter');

+    // Final state verification
     await assertHTML(page, html`...`);
     expect(await page.isVisible('[data-testid="cta-button"]')).toBe(true);
 });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b01b14 and 193d7cd.

📒 Files selected for processing (3)
  • packages/koenig-lexical/src/components/ui/cards/CtaCard.jsx (1 hunks)
  • packages/koenig-lexical/src/nodes/CallToActionNodeComponent.jsx (2 hunks)
  • packages/koenig-lexical/test/e2e/cards/cta-card.test.js (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/koenig-lexical/src/components/ui/cards/CtaCard.jsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Node 20.11.1
🔇 Additional comments (1)
packages/koenig-lexical/src/nodes/CallToActionNodeComponent.jsx (1)

50-55: LGTM! Clean implementation of URL handling.

The handleButtonUrlChange implementation follows the established patterns in the codebase and correctly integrates with Lexical's editor API.

Also applies to: 78-78

Comment on lines 77 to 100
// NOTE: an improvement would be to pass in suggested url options, but the construction now doesn't make that straightforward
test('suggested urls display', async function () {
await focusEditor(page);
await insertCard(page, {cardName: 'call-to-action'});
await page.click('[data-testid="button-settings"]');

const buttonTextInput = await page.getByTestId('button-url');
await expect(buttonTextInput).toHaveValue('');

// this is dependent on the test values inserted in the node
await page.getByTestId('button-url').fill('Ho');
// // this is too fast, need to try two inputs or add a delay before checking the suggested options
await page.getByTestId('button-url').fill('me');
await expect(await page.getByTestId('button-url-listOption')).toContainText('Homepage');
// click on homepage
await page.getByTestId('button-url-listOption').click();
// check if the url is set
const buttonContainer = await page.$('[data-test-cta-button-current-url]');
const currentUrl = await buttonContainer.getAttribute('data-test-cta-button-current-url');
// current view can be any url, so check for a valid url
const validUrlRegex = /^(https?:\/\/)([\w.-]+)(:[0-9]+)?(\/[\w.-]*)*(\?.*)?(#.*)?$/;
// Assert the URL is valid
expect(currentUrl).toMatch(validUrlRegex);
});
Copy link

@coderabbitai coderabbitai bot Jan 23, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Address potential flakiness in URL suggestions test.

A few concerns with the current implementation:

  1. The comment about timing suggests potential test flakiness
  2. Test relies on hardcoded test data ("Ho", "me", "Homepage")
  3. URL validation regex might be too permissive

Consider these improvements:

  1. Use waitFor or similar mechanism instead of relying on multiple input events
  2. Inject test data through test configuration
  3. Use a stricter URL validation regex or a dedicated URL validation library
- // this is too fast, need to try two inputs or add a delay before checking the suggested options
- await page.getByTestId('button-url').fill('Ho');
- await page.getByTestId('button-url').fill('me');
+ await page.getByTestId('button-url').fill('Home');
+ await page.waitForSelector('[data-testid="button-url-listOption"]');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// NOTE: an improvement would be to pass in suggested url options, but the construction now doesn't make that straightforward
test('suggested urls display', async function () {
await focusEditor(page);
await insertCard(page, {cardName: 'call-to-action'});
await page.click('[data-testid="button-settings"]');
const buttonTextInput = await page.getByTestId('button-url');
await expect(buttonTextInput).toHaveValue('');
// this is dependent on the test values inserted in the node
await page.getByTestId('button-url').fill('Ho');
// // this is too fast, need to try two inputs or add a delay before checking the suggested options
await page.getByTestId('button-url').fill('me');
await expect(await page.getByTestId('button-url-listOption')).toContainText('Homepage');
// click on homepage
await page.getByTestId('button-url-listOption').click();
// check if the url is set
const buttonContainer = await page.$('[data-test-cta-button-current-url]');
const currentUrl = await buttonContainer.getAttribute('data-test-cta-button-current-url');
// current view can be any url, so check for a valid url
const validUrlRegex = /^(https?:\/\/)([\w.-]+)(:[0-9]+)?(\/[\w.-]*)*(\?.*)?(#.*)?$/;
// Assert the URL is valid
expect(currentUrl).toMatch(validUrlRegex);
});
// NOTE: an improvement would be to pass in suggested url options, but the construction now doesn't make that straightforward
test('suggested urls display', async function () {
await focusEditor(page);
await insertCard(page, {cardName: 'call-to-action'});
await page.click('[data-testid="button-settings"]');
const buttonTextInput = await page.getByTestId('button-url');
await expect(buttonTextInput).toHaveValue('');
await page.getByTestId('button-url').fill('Home');
await page.waitForSelector('[data-testid="button-url-listOption"]');
await expect(await page.getByTestId('button-url-listOption')).toContainText('Homepage');
// click on homepage
await page.getByTestId('button-url-listOption').click();
// check if the url is set
const buttonContainer = await page.$('[data-test-cta-button-current-url]');
const currentUrl = await buttonContainer.getAttribute('data-test-cta-button-current-url');
// current view can be any url, so check for a valid url
const validUrlRegex = /^(https?:\/\/)([\w.-]+)(:[0-9]+)?(\/[\w.-]*)*(\?.*)?(#.*)?$/;
// Assert the URL is valid
expect(currentUrl).toMatch(validUrlRegex);
});

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed it, thanks.

Copy link

Choose a reason for hiding this comment

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

@ronaldlangeveld You're welcome! The test looks much more robust now. 🎉

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
packages/koenig-lexical/test/e2e/cards/cta-card.test.js (3)

67-75: Consider adding edge cases for URL validation.

The test verifies basic URL setting functionality well. Consider adding test cases for:

  1. Invalid URLs
  2. URLs with special characters
  3. Empty URL handling
test('handles invalid button urls', async function () {
    await focusEditor(page);
    await insertCard(page, {cardName: 'call-to-action'});
    await page.click('[data-testid="button-settings"]');
    
    // Test invalid URL
    await page.fill('[data-testid="button-url"]', 'not-a-url');
    const buttonContainer = await page.$('[data-test-cta-button-current-url]');
    const currentUrl = await buttonContainer.getAttribute('data-test-cta-button-current-url');
    expect(currentUrl).toBe(''); // or expect appropriate error handling
});

94-96: Extract URL validation regex to a shared constant.

The URL validation regex is well-defined but should be:

  1. Extracted to a shared constant for reuse
  2. Enhanced to handle more edge cases (e.g., IDN domains)
+ // In a shared constants file
+ export const URL_VALIDATION = {
+   pattern: /^(https?:\/\/)([\w.-]+)(:[0-9]+)?(\/[\w.-]*)*(\?.*)?(#.*)?$/,
+   message: 'Invalid URL format'
+ };

- const validUrlRegex = /^(https?:\/\/)([\w.-]+)(:[0-9]+)?(\/[\w.-]*)*(\?.*)?(#.*)?$/;
+ const {pattern: validUrlRegex} = URL_VALIDATION;

99-126: Improve test organization and naming.

While the test covers the requirements well, consider:

  1. Splitting into smaller, focused test cases
  2. Using a more descriptive test name
  3. Adding comments for each test phase
- test('button doesnt disappear when toggled, has text, has url and loses focus', async function () {
+ test('maintains button state and visibility after configuration', async function () {

Consider splitting into:

test('maintains button visibility after losing focus', async function () {
    // Setup
    // Action: lose focus
    // Assert visibility
});

test('preserves button configuration in non-editing mode', async function () {
    // Setup
    // Action: exit editing mode
    // Assert configuration
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 193d7cd and 86a98df.

📒 Files selected for processing (2)
  • packages/koenig-lexical/test/e2e/cards/button-card.test.js (1 hunks)
  • packages/koenig-lexical/test/e2e/cards/cta-card.test.js (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Node 20.11.1
🔇 Additional comments (1)
packages/koenig-lexical/test/e2e/cards/button-card.test.js (1)

137-138: Good fix for test flakiness, but further improvements possible.

The changes address the timing issues by using a single input event and explicit wait. However, consider these additional improvements:

  1. Extract test data ("Home", "Homepage") to test configuration
  2. Add timeout to waitForSelector for better error handling
  3. Consider testing edge cases (empty input, special characters)
+ const TEST_DATA = {
+   input: 'Home',
+   expected: 'Homepage'
+ };
- await page.getByTestId('button-input-url').fill('Home');
- await page.waitForSelector('[data-testid="button-input-url-listOption"]');
+ await page.getByTestId('button-input-url').fill(TEST_DATA.input);
+ await page.waitForSelector('[data-testid="button-input-url-listOption"]', {timeout: 5000});

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