MarkdownContent.stories.svelte 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <script module lang="ts">
  2. import { defineMeta } from '@storybook/addon-svelte-csf';
  3. import { expect } from 'storybook/test';
  4. import { MarkdownContent } from '$lib/components/app';
  5. import { AI_TUTORIAL_MD } from './fixtures/ai-tutorial.js';
  6. import { API_DOCS_MD } from './fixtures/api-docs.js';
  7. import { BLOG_POST_MD } from './fixtures/blog-post.js';
  8. import { DATA_ANALYSIS_MD } from './fixtures/data-analysis.js';
  9. import { README_MD } from './fixtures/readme.js';
  10. import { MATH_FORMULAS_MD } from './fixtures/math-formulas.js';
  11. import { EMPTY_MD } from './fixtures/empty.js';
  12. const { Story } = defineMeta({
  13. title: 'Components/MarkdownContent',
  14. component: MarkdownContent,
  15. parameters: {
  16. layout: 'centered'
  17. }
  18. });
  19. </script>
  20. <Story name="Empty" args={{ content: EMPTY_MD, class: 'max-w-[56rem] w-[calc(100vw-2rem)]' }} />
  21. <Story
  22. name="AI Tutorial"
  23. args={{ content: AI_TUTORIAL_MD, class: 'max-w-[56rem] w-[calc(100vw-2rem)]' }}
  24. />
  25. <Story
  26. name="API Documentation"
  27. args={{ content: API_DOCS_MD, class: 'max-w-[56rem] w-[calc(100vw-2rem)]' }}
  28. />
  29. <Story
  30. name="Technical Blog"
  31. args={{ content: BLOG_POST_MD, class: 'max-w-[56rem] w-[calc(100vw-2rem)]' }}
  32. />
  33. <Story
  34. name="Data Analysis"
  35. args={{ content: DATA_ANALYSIS_MD, class: 'max-w-[56rem] w-[calc(100vw-2rem)]' }}
  36. />
  37. <Story
  38. name="README file"
  39. args={{ content: README_MD, class: 'max-w-[56rem] w-[calc(100vw-2rem)]' }}
  40. />
  41. <Story
  42. name="Math Formulas"
  43. args={{ content: MATH_FORMULAS_MD, class: 'max-w-[56rem] w-[calc(100vw-2rem)]' }}
  44. />
  45. <Story
  46. name="URL Links"
  47. args={{
  48. content: `# URL Links Test
  49. Here are some example URLs that should open in new tabs:
  50. - [Hugging Face Homepage](https://huggingface.co)
  51. - [GitHub Repository](https://github.com/ggml-org/llama.cpp)
  52. - [OpenAI Website](https://openai.com)
  53. - [Google Search](https://www.google.com)
  54. You can also test inline links like https://example.com or https://docs.python.org.
  55. All links should have \`target="_blank"\` and \`rel="noopener noreferrer"\` attributes for security.`,
  56. class: 'max-w-[56rem] w-[calc(100vw-2rem)]'
  57. }}
  58. play={async ({ canvasElement }) => {
  59. // Wait for component to render
  60. await new Promise((resolve) => setTimeout(resolve, 100));
  61. // Find all links in the rendered content
  62. const links = canvasElement.querySelectorAll('a[href]');
  63. // Test that we have the expected number of links
  64. expect(links.length).toBeGreaterThan(0);
  65. // Test each link for proper attributes
  66. links.forEach((link) => {
  67. const href = link.getAttribute('href');
  68. // Test that external links have proper security attributes
  69. if (href && (href.startsWith('http://') || href.startsWith('https://'))) {
  70. expect(link.getAttribute('target')).toBe('_blank');
  71. expect(link.getAttribute('rel')).toBe('noopener noreferrer');
  72. }
  73. });
  74. // Test specific links exist
  75. const hugginFaceLink = Array.from(links).find(
  76. (link) => link.getAttribute('href') === 'https://huggingface.co'
  77. );
  78. expect(hugginFaceLink).toBeTruthy();
  79. expect(hugginFaceLink?.textContent).toBe('Hugging Face Homepage');
  80. const githubLink = Array.from(links).find(
  81. (link) => link.getAttribute('href') === 'https://github.com/ggml-org/llama.cpp'
  82. );
  83. expect(githubLink).toBeTruthy();
  84. expect(githubLink?.textContent).toBe('GitHub Repository');
  85. const openaiLink = Array.from(links).find(
  86. (link) => link.getAttribute('href') === 'https://openai.com'
  87. );
  88. expect(openaiLink).toBeTruthy();
  89. expect(openaiLink?.textContent).toBe('OpenAI Website');
  90. const googleLink = Array.from(links).find(
  91. (link) => link.getAttribute('href') === 'https://www.google.com'
  92. );
  93. expect(googleLink).toBeTruthy();
  94. expect(googleLink?.textContent).toBe('Google Search');
  95. // Test inline links (auto-linked URLs)
  96. const exampleLink = Array.from(links).find(
  97. (link) => link.getAttribute('href') === 'https://example.com'
  98. );
  99. expect(exampleLink).toBeTruthy();
  100. const pythonDocsLink = Array.from(links).find(
  101. (link) => link.getAttribute('href') === 'https://docs.python.org'
  102. );
  103. expect(pythonDocsLink).toBeTruthy();
  104. console.log(`✅ URL Links test passed - Found ${links.length} links with proper attributes`);
  105. }}
  106. />