Skip to content

[Tests Migration] fluentTheme/customElement tests #5498

Open
@OEvgeny

Description

@OEvgeny

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

Metadata

Metadata

Assignees

Labels

✨ CopilotIssues specifically designed for Copilot

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions