microsoft / microsoft/BotFramework-WebChat

[Tests Migration] fluentTheme/customElement tests

Open
#5,498 0 comments 1 reaction 1 assignee View on GitHub

Nobody has claimed this yet.

✨ Copilot
Dominant language
HTML
Stars
1.8k
Forks
1.6k
Avg merge
22h 58m
Merged PRs (30d)
2

Description

Following the below guide migrate tests located in folder:

__tests__/html/fluentTheme/customElement

Migrating BotFramework-WebChat Tests from html to html2

This guide covers the migration process from the legacy __tests__/html test structure to the modern __tests__/html2 structure, based on the simplified migration patterns established in the BotFramework-WebChat project.

Overview

The migration involves updating test files to use:

  • ES Modules (ESM) instead of Babel transpilation
  • CDN dependencies for React instead of bundled assets
  • Global renderWebChat function where possible for consistent rendering
  • Theme and variant query parameters where appropriate for consistent theming

Migration Steps

1. File Structure and Organization
Creating Test Directories
# Create the html2 directory structure or check existance
mkdir -p __tests__/html2/[feature-name]/
File Naming Convention
  • Main test file: [testName].html
  • Theme/variant files: [testName].[theme].[variant].html (redirect files)
  • Examples:
    • typingIndicator.scroll.fluent.copilot.html
    • layout.fluent.html
2. HTML Document Structure Migration
Before (Legacy Structure)
<!DOCTYPE html>
<html lang="en-US">
<head>
  <script crossorigin="anonymous" src="https://unpkg.com/@babel/standalone@7.8.7/babel.min.js"></script>
  <script crossorigin="anonymous" src="https://unpkg.com/react@16.8.6/umd/react.development.js"></script>
  <script crossorigin="anonymous" src="https://unpkg.com/react-dom@16.8.6/umd/react-dom.development.js"></script>
  <!-- More UMD scripts -->
</head>
After (Modern Structure)
<!doctype html>
<html lang="en-US">
  <head>
    <link href="/assets/index.css" rel="stylesheet" type="text/css" />
    <script type="importmap">
      {
        "imports": {
          "react": "https://esm.sh/react@18.3.1",
          "react-dom": "https://esm.sh/react-dom@18.3.1",
          "react-dom/": "https://esm.sh/react-dom@18.3.1/"
        }
      }
    </script>
    <script crossorigin="anonymous" src="/test-harness.js"></script>
    <script crossorigin="anonymous" src="/test-page-object.js"></script>
    <script type="module">
      import React from 'react';
      window.React = React;
    </script>
    <script defer crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
    <script defer crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.production.min.js"></script>
  </head>
3. Dependency Management
Remove These Dependencies
  • @babel/standalone
Keep These Dependencies
<!-- Test infrastructure -->
<script crossorigin="anonymous" src="/test-harness.js"></script>
<script crossorigin="anonymous" src="/test-page-object.js"></script>

<!-- defer WebChat bundles to wait for React availability -->
<script defer crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
<script defer crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.production.min.js"></script>
Optional ES Module Imports
<!-- Add more into import map if needed for specific test dependencies -->
<script type="importmap">
  {
    "imports": {
      "react": "https://esm.sh/react@18.3.1",
      "react-dom": "https://esm.sh/react-dom@18.3.1",
      "react-dom/": "https://esm.sh/react-dom@18.3.1/",
      "@testduet/wait-for": "https://unpkg.com/@testduet/wait-for@main/dist/wait-for.mjs",
      "jest-mock": "https://esm.sh/jest-mock"
    }
  }
</script>
4. Using the Global renderWebChat Function

Where appropriate use the globaly available renderWebChat function which respects query parameters

Basic Usage
// The renderWebChat function is globally available
run(async function () {
  const { directLine, store } = testHelpers.createDirectLineEmulator();

  // Simple rendering - theme and variant handled automatically via query params
  renderWebChat(
    { directLine, store },
    document.getElementById('webchat')
  );

  await pageConditions.uiConnected();
  
  // Test logic...
  
  await host.snapshot('local');
});
With Additional Props
run(async function () {
  const { directLine, store } = testHelpers.createDirectLineEmulator();

  await host.sendDevToolsCommand('Emulation.setEmulatedMedia', {
    features: [{ name: 'prefers-reduced-motion', value: 'reduce' }]
  });

  renderWebChat(
    { 
      directLine, 
      store,
      styleOptions: {
        botAvatarBackgroundColor: '#304E7A',
        // other style options
      }
    },
    document.getElementById('webchat')
  );

  await pageConditions.uiConnected();
  // Test continues...
});
5. Theme and Variant Redirect Files

Create simple redirect files for different theme/variant combinations.

It works only with the global renderWebChat function. If you can't use it, handle query paramters explicitly in the test file.

Example: Fluent Copilot Theme
<!-- typingIndicator.scroll.fluent.copilot.html -->
<!doctype html>
<html>
  <head>
    <script>
      location = './typingIndicator.scroll?theme=fluent&variant=copilot';
    </script>
  </head>
  <body></body>
</html>
Supported Query Parameters
  • theme=fluent - Enables Fluent theme
  • variant=copilot - Enables Copilot variant (requires Fluent theme)
6. ES Module Script Structure
Modern Script Section
<script type="module">
  // Import ES modules if needed
  import { waitFor } from '@testduet/wait-for';

  // Access query parameters
  const isLivestream = new URL(location).searchParams.has('livestream');

  run(async function () {
    // Test logic using global renderWebChat function
    const { directLine, store } = testHelpers.createDirectLineEmulator();
    
    renderWebChat(
      { directLine, store },
      document.getElementById('webchat')
    );

    await pageConditions.uiConnected();
    // Continue with test...
  });
</script>
7. Removed Complexity
No More JSX to React.createElement Conversion
// ❌ OLD: Manual createElement calls
React.createElement(
  FluentProvider,
  { theme: fluentTheme },
  React.createElement(FluentThemeProvider, ...)
);

// ✅ NEW: Handled by either global renderWebChat
renderWebChat({ directLine, store }, container);

Common Migration Patterns

1. Simple Feature Test Migration
<!doctype html>
<html lang="en-US">
  <head>
    <link href="/assets/index.css" rel="stylesheet" type="text/css" />
    <script type="importmap">
      {
        "imports": {
          "react": "https://esm.sh/react@18.3.1",
          "react-dom": "https://esm.sh/react-dom@18.3.1",
          "react-dom/": "https://esm.sh/react-dom@18.3.1/"
        }
      }
    </script>
    <script crossorigin="anonymous" src="/test-harness.js"></script>
    <script crossorigin="anonymous" src="/test-page-object.js"></script>
    <script type="module">
      import React from 'react';
      window.React = React;
    </script>
    <script defer crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
    <script defer crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.production.min.js"></script>
  </head>
  <body>
    <main id="webchat"></main>
    <script type="module">
      run(async function () {
        const { directLine, store } = testHelpers.createDirectLineEmulator();

        renderWebChat(
          { directLine, store },
          document.getElementById('webchat')
        );

        await pageConditions.uiConnected();
        
        // Test logic...
        
        await host.snapshot('local');
      });
    </script>
  </body>
</html>
2. Feature Test with ES Module Dependencies
<!doctype html>
<html lang="en-US">
  <head>
    <link href="/assets/index.css" rel="stylesheet" type="text/css" />
    <script type="importmap">
      {
        "imports": {
          "react": "https://esm.sh/react@18.3.1",
          "react-dom": "https://esm.sh/react-dom@18.3.1",
          "react-dom/": "https://esm.sh/react-dom@18.3.1/",
          "@testduet/wait-for": "https://unpkg.com/@testduet/wait-for@main/dist/wait-for.mjs"
        }
      }
    </script>
    <script crossorigin="anonymous" src="/test-harness.js"></script>
    <script crossorigin="anonymous" src="/test-page-object.js"></script>
    <script type="module">
      import React from 'react';
      window.React = React;
    </script>
    <script defer crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
    <script defer crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.production.min.js"></script>
  </head>
  <body>
    <main id="webchat"></main>
    <script type="module">
      import { waitFor } from '@testduet/wait-for';

      run(async function () {
        const { directLine, store } = testHelpers.createDirectLineEmulator();

        renderWebChat(
          { directLine, store },
          document.getElementById('webchat')
        );

        await pageConditions.uiConnected();
        
        // Use imported modules
        await waitFor(() => expect(someCondition()).toBeTruthy());
        
        await host.snapshot('local');
      });
    </script>
  </body>
</html>
3. Feature Test with Custom Styling
<!doctype html>
<html lang="en-US">
  <head>
    <link href="/assets/index.css" rel="stylesheet" type="text/css" />
    <script type="importmap">
      {
        "imports": {
          "react": "https://esm.sh/react@18.3.1",
          "react-dom": "https://esm.sh/react-dom@18.3.1",
          "react-dom/": "https://esm.sh/react-dom@18.3.1/",
          "@testduet/wait-for": "https://unpkg.com/@testduet/wait-for@main/dist/wait-for.mjs"
        }
      }
    </script>
    <script crossorigin="anonymous" src="/test-harness.js"></script>
    <script crossorigin="anonymous" src="/test-page-object.js"></script>
    <script type="module">
      import React from 'react';
      window.React = React;
    </script>
    <script defer crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
    <script defer crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.production.min.js"></script>
    <style>
      #webchat .webchat__typing-indicator {
        background-image: url(data:image/gif;base64,/* custom styling */);
        background-color: black;
      }
    </style>
  </head>
  <body>
    <main id="webchat"></main>
    <script type="module">
      run(async function () {
        await host.sendDevToolsCommand('Emulation.setEmulatedMedia', {
          features: [{ name: 'prefers-reduced-motion', value: 'reduce' }]
        });

        const { directLine, store } = testHelpers.createDirectLineEmulator();

        renderWebChat(
          { directLine, store },
          document.getElementById('webchat')
        );

        await pageConditions.uiConnected();
        // Test continues...
      });
    </script>
  </body>
</html>

Migration Checklist

Before Migration
  • Identify the test's purpose and required dependencies
  • Note any special styling or configuration requirements
  • Check for Babel usage that needs removal
  • Identify theme/variant requirements by looking into similar test files test-file-name.*
During Migration
  • Create new directory structure in __tests__/html2
  • Replace Babel with ES module script (if needed)
  • Replace manual rendering with renderWebChat() calls if possible
  • Update snapshot calls to use 'local'
  • Create theme/variant redirect files if needed
After Migration
  • Test default rendering
  • Test theme/variant combinations via redirects
  • Verify all test functionality works
  • Check that snapshots are generated correctly
  • Ensure any ES module dependencies load correctly

Query Parameter Reference

The renderWebChat global function automatically handles these query parameters:

Parameter Values Description
theme fluent Enables Fluent theme rendering
variant copilot Enables Copilot variant (requires theme=fluent)
Example URLs
  • Default: test assuming filename is test.html
  • Fluent theme: test?theme=fluent
  • Copilot variant: test?theme=fluent&variant=copilot
  • custom: test?custom=optional-value for custom test cases (handled explicitly in the test file)

Troubleshooting

Common Issues
  1. renderWebChat not defined

    • Ensure /test-page-object.js is loaded
  2. Theme not applying

    • Verify query parameters are correct
    • Ensure fluent-theme bundle is loaded
  3. ES module import errors

    • Check importmap syntax and URLs
    • Verify ESM dependencies are actually needed

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.