From 9dde5f63c7adb00efea2f719d0657f7d7269d707 Mon Sep 17 00:00:00 2001 From: alvarosabu Date: Wed, 18 Dec 2024 09:52:26 +0100 Subject: [PATCH 1/4] chore: pnpm workspaces and granular CI --- .github/ISSUE_TEMPLATE/config.yml | 2 +- .github/ISSUE_TEMPLATE/issue.bug.yml | 4 +- .github/ISSUE_TEMPLATE/issue.fr.yml | 6 +- .github/dependabot.yml | 34 +- .github/workflows/commitlint.yml | 31 + .github/workflows/dependabot-automerge.yml | 4 +- .github/workflows/lint.yml | 28 + .github/workflows/pkg.pr.new.yml | 38 + .github/workflows/release.yml | 23 +- .github/workflows/test.yml | 50 + .husky/commit-msg | 6 - .husky/pre-commit | 4 - cypress.config.ts | 38 + cypress/components/index.cy.ts | 295 + .../testing-components/Essential.vue | 44 +- .../testing-components}/IFrameEmbed.vue | 1 + .../testing-components/RealApi.vue | 8 +- .../testing-components/RealApiChild.vue | 11 +- .../testing-components/RichText.vue | 3 +- .../testing-components/RichTextChild.vue | 0 .../cypress => cypress}/fixtures/example.json | 0 cypress/support/commands.ts | 37 + .../support/component-index.html | 10 +- {lib/cypress => cypress}/support/component.ts | 0 {lib/cypress => cypress}/support/e2e.ts | 0 eslint.config.js | 5 + lib/__tests__/.eslintrc | 5 - lib/__tests__/index.test.js | 15 - lib/cypress.config.ts | 23 - lib/cypress/.eslintrc | 3 - lib/cypress/components/index.cy.js | 293 - lib/index.ts | 125 - lib/package.json | 94 - lib/tsconfig.json | 15 - lib/vite.config.ts | 26 - package-lock.json | 10766 ---------------- package.json | 133 +- playground/main.ts | 29 - playground/package.json | 20 - playground/router/index.ts | 20 - playground/tsconfig.json | 12 - playground/vite.config.ts | 15 - playground/vue/.gitignore | 24 + playground/vue/.vscode/extensions.json | 3 + playground/vue/README.md | 5 + playground/{ => vue}/index.html | 8 +- playground/vue/package.json | 23 + playground/vue/public/vite.svg | 1 + playground/{ => vue/src}/App.vue | 9 +- playground/vue/src/assets/vue.svg | 1 + .../{ => vue/src}/components/Feature.vue | 0 playground/{ => vue/src}/components/Grid.vue | 2 +- .../vue/src/components}/IFrameEmbed.vue | 0 .../src}/components/MyCustomFallback.vue | 0 playground/{ => vue/src}/components/Page.vue | 0 .../{ => vue/src}/components/Teaser.vue | 0 playground/vue/src/main.ts | 30 + playground/{ => vue/src}/pages/Home.vue | 15 +- playground/{ => vue/src}/pages/HomeShort.vue | 8 +- .../{ => vue/src}/pages/RichTextDemo.vue | 30 +- playground/vue/src/router/index.ts | 20 + playground/vue/src/style.css | 0 playground/vue/src/vite-env.d.ts | 1 + playground/vue/tsconfig.app.json | 26 + playground/vue/tsconfig.json | 7 + playground/vue/tsconfig.node.json | 24 + playground/vue/vite.config.ts | 18 + pnpm-lock.yaml | 6424 +++++++++ pnpm-workspace.yaml | 2 + {lib => src/components}/FallbackComponent.vue | 21 +- .../components}/StoryblokComponent.vue | 29 +- {lib => src}/components/StoryblokRichText.vue | 10 +- .../composables/useStoryblokRichText.ts | 14 +- src/index.ts | 131 + {lib => src}/types.ts | 42 +- src/vite-env.d.ts | 3 + tsconfig.json | 28 +- tsconfig.node.json | 11 + vite.config.ts | 44 + 79 files changed, 7582 insertions(+), 11708 deletions(-) create mode 100644 .github/workflows/commitlint.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/pkg.pr.new.yml create mode 100644 .github/workflows/test.yml delete mode 100755 .husky/commit-msg delete mode 100755 .husky/pre-commit create mode 100644 cypress.config.ts create mode 100644 cypress/components/index.cy.ts rename {lib/cypress => cypress/components}/testing-components/Essential.vue (70%) rename {playground/components => cypress/components/testing-components}/IFrameEmbed.vue (99%) rename {lib/cypress => cypress/components}/testing-components/RealApi.vue (74%) rename {lib/cypress => cypress/components}/testing-components/RealApiChild.vue (52%) rename {lib/cypress => cypress/components}/testing-components/RichText.vue (74%) rename {lib/cypress => cypress/components}/testing-components/RichTextChild.vue (100%) rename {lib/cypress => cypress}/fixtures/example.json (100%) create mode 100644 cypress/support/commands.ts rename {lib/cypress => cypress}/support/component-index.html (64%) rename {lib/cypress => cypress}/support/component.ts (100%) rename {lib/cypress => cypress}/support/e2e.ts (100%) create mode 100644 eslint.config.js delete mode 100644 lib/__tests__/.eslintrc delete mode 100644 lib/__tests__/index.test.js delete mode 100644 lib/cypress.config.ts delete mode 100644 lib/cypress/.eslintrc delete mode 100644 lib/cypress/components/index.cy.js delete mode 100644 lib/index.ts delete mode 100644 lib/package.json delete mode 100644 lib/tsconfig.json delete mode 100644 lib/vite.config.ts delete mode 100644 package-lock.json delete mode 100644 playground/main.ts delete mode 100644 playground/package.json delete mode 100644 playground/router/index.ts delete mode 100644 playground/tsconfig.json delete mode 100644 playground/vite.config.ts create mode 100644 playground/vue/.gitignore create mode 100644 playground/vue/.vscode/extensions.json create mode 100644 playground/vue/README.md rename playground/{ => vue}/index.html (59%) create mode 100644 playground/vue/package.json create mode 100644 playground/vue/public/vite.svg rename playground/{ => vue/src}/App.vue (65%) create mode 100644 playground/vue/src/assets/vue.svg rename playground/{ => vue/src}/components/Feature.vue (100%) rename playground/{ => vue/src}/components/Grid.vue (92%) rename {lib/cypress/testing-components => playground/vue/src/components}/IFrameEmbed.vue (100%) rename playground/{ => vue/src}/components/MyCustomFallback.vue (100%) rename playground/{ => vue/src}/components/Page.vue (100%) rename playground/{ => vue/src}/components/Teaser.vue (100%) create mode 100644 playground/vue/src/main.ts rename playground/{ => vue/src}/pages/Home.vue (79%) rename playground/{ => vue/src}/pages/HomeShort.vue (50%) rename playground/{ => vue/src}/pages/RichTextDemo.vue (69%) create mode 100644 playground/vue/src/router/index.ts create mode 100644 playground/vue/src/style.css create mode 100644 playground/vue/src/vite-env.d.ts create mode 100644 playground/vue/tsconfig.app.json create mode 100644 playground/vue/tsconfig.json create mode 100644 playground/vue/tsconfig.node.json create mode 100644 playground/vue/vite.config.ts create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml rename {lib => src/components}/FallbackComponent.vue (77%) rename {lib => src/components}/StoryblokComponent.vue (57%) rename {lib => src}/components/StoryblokRichText.vue (72%) rename {lib => src}/composables/useStoryblokRichText.ts (69%) create mode 100644 src/index.ts rename {lib => src}/types.ts (79%) create mode 100644 src/vite-env.d.ts create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index ec4bb38..3ba13e0 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1 +1 @@ -blank_issues_enabled: false \ No newline at end of file +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/issue.bug.yml b/.github/ISSUE_TEMPLATE/issue.bug.yml index 1c719c2..ab52aaf 100644 --- a/.github/ISSUE_TEMPLATE/issue.bug.yml +++ b/.github/ISSUE_TEMPLATE/issue.bug.yml @@ -1,4 +1,4 @@ -name: "\U0001F41E SDK Bug Report" +name: 🐞 SDK Bug Report description: Report an issue using Vue 3 Storyblok SDK labels: [pending-triage, pending-author] body: @@ -11,7 +11,7 @@ body: attributes: label: Describe the issue you're facing description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description so we can review it. Thanks in advance! - placeholder: My Vue 3 Storyblok SDK configuration is ... ## Expected behavior ... ## Current Behavior ... + placeholder: My Vue 3 Storyblok SDK configuration is ... # # Expected behavior ... ## Current Behavior ... validations: required: true - type: input diff --git a/.github/ISSUE_TEMPLATE/issue.fr.yml b/.github/ISSUE_TEMPLATE/issue.fr.yml index 3663af2..bacc65c 100644 --- a/.github/ISSUE_TEMPLATE/issue.fr.yml +++ b/.github/ISSUE_TEMPLATE/issue.fr.yml @@ -1,4 +1,4 @@ -name: "\U0001F58C SDK Feature Request" +name: 🖌 SDK Feature Request description: Propose a feature or improvement that the Storyblok SDK should have labels: [enhancement, pending-triage, pending-author] body: @@ -10,7 +10,7 @@ body: id: feature-description attributes: label: Description - description: "Clear and concise description of what you want to include or enhance from the SDK. Please make the reason and usecases as detailed as possible. If you intend to submit a PR for this feature request, tell us in the description so we can review and be aware of it. Thanks in advance!" + description: 'Clear and concise description of what you want to include or enhance from the SDK. Please make the reason and usecases as detailed as possible. If you intend to submit a PR for this feature request, tell us in the description so we can review and be aware of it. Thanks in advance!' placeholder: As a developer using Storyblok SDK I want [wish] so that [benefit]. validations: required: true @@ -18,7 +18,7 @@ body: id: suggested-solution attributes: label: Suggested solution or improvement - description: "Link to the PR or what implementation you will expect from us (links to external examples if needed)." + description: Link to the PR or what implementation you will expect from us (links to external examples if needed). validations: required: true - type: textarea diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1644135..e5cb88d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,10 +1,10 @@ version: 2 updates: - - package-ecosystem: "npm" - directory: "/" + - package-ecosystem: npm + directory: / schedule: - interval: "daily" - time: "04:00" + interval: daily + time: '04:00' commit-message: prefix: fix prefix-development: chore @@ -12,20 +12,20 @@ updates: groups: linting-dx-tools: patterns: - - "*lint*" # eslint, eslint-*, vue-eslint-parser, lint-staged, @commitlint/*, @typescript-eslint/* - - "prettier" - - "husky" - - "@vue/tsconfig" - - "*babel*" # babel-*, @vue/babel-preset-app, @babel/* + - '*lint*' # eslint, eslint-*, vue-eslint-parser, lint-staged, @commitlint/*, @typescript-eslint/* + - prettier + - husky + - '@vue/tsconfig' + - '*babel*' # babel-*, @vue/babel-preset-app, @babel/* update-types: - - "minor" - - "patch" + - minor + - patch testing-tools: patterns: - - "cypress" - - "@cypress/*" - - "@vue/test-utils" - - "*jest*" # jest, babel-jest, @vue/vue3-jest + - cypress + - '@cypress/*' + - '@vue/test-utils' + - '*jest*' # jest, babel-jest, @vue/vue3-jest update-types: - - "minor" - - "patch" + - minor + - patch diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 0000000..122fb09 --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,31 @@ +name: CI + +on: [push, pull_request] + +env: + PNPM_CACHE_FOLDER: .pnpm-store + SKIP_INSTALL_SIMPLE_GIT_HOOKS: 1 # Skip installing simple-git-hooks + +jobs: + commitlint: + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup pnpm + uses: pnpm/action-setup@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: pnpm + - name: Install dependencies + run: pnpm install + - name: Validate current commit (last commit) with commitlint + if: github.event_name == 'push' + run: pnpm commitlint --last --verbose + - name: Validate PR commits with commitlint + if: github.event_name == 'pull_request' + run: pnpm commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose diff --git a/.github/workflows/dependabot-automerge.yml b/.github/workflows/dependabot-automerge.yml index 6581c0f..136c0c6 100644 --- a/.github/workflows/dependabot-automerge.yml +++ b/.github/workflows/dependabot-automerge.yml @@ -18,11 +18,11 @@ jobs: id: metadata uses: dependabot/fetch-metadata@v1.1.1 with: - github-token: "${{ secrets.GITHUB_TOKEN }}" + github-token: '${{ secrets.GITHUB_TOKEN }}' - name: Enable auto-merge for Dependabot PRs if: ${{contains(steps.metadata.outputs.dependency-names, env.DEPENDENCY) && (steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor')}} run: gh pr merge --auto --merge "$PR_URL" env: - DEPENDENCY: "@storyblok/js" + DEPENDENCY: '@storyblok/js' PR_URL: ${{github.event.pull_request.html_url}} GITHUB_TOKEN: ${{secrets.DEPENDABOT_TOKEN}} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..1eb2b19 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,28 @@ +name: Run linters +on: [push] + +env: + PNPM_CACHE_FOLDER: .pnpm-store + SKIP_INSTALL_SIMPLE_GIT_HOOKS: 1 # Skip installing simple-git-hooks + +jobs: + lint: + name: Lint + runs-on: ubuntu-24.04 + strategy: + matrix: + node-version: [20] + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup pnpm + uses: pnpm/action-setup@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: pnpm + - name: Install dependencies + run: pnpm install + - name: Run Lint + run: pnpm run lint diff --git a/.github/workflows/pkg.pr.new.yml b/.github/workflows/pkg.pr.new.yml new file mode 100644 index 0000000..bba7be8 --- /dev/null +++ b/.github/workflows/pkg.pr.new.yml @@ -0,0 +1,38 @@ +name: Publish Any Commit +on: + push: + branches: + - '**' + tags: + - '!**' + +env: + PNPM_CACHE_FOLDER: .pnpm-store + HUSKY: 0 # Bypass husky commit hook for CI + +permissions: {} + +concurrency: + group: ${{ github.workflow }}-${{ github.event.number }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-24.04 + strategy: + matrix: + node-version: [20] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - run: corepack enable + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: pnpm + - name: Install dependencies + run: pnpm install + - name: Build + run: pnpm build + - run: pnpx pkg-pr-new publish --compact --pnpm diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c4a3c3e..3fe0979 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,23 +11,20 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 - - name: Setup Node - uses: actions/setup-node@v3 + uses: actions/checkout@v4 + - name: Setup pnpm + uses: pnpm/action-setup@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 with: - node-version: "18" - cache: "npm" + node-version: ${{ matrix.node-version }} + cache: pnpm - name: Install dependencies - run: npm ci + run: pnpm install - name: Build lib - run: npm run build - - name: Jest run - run: npm run test:unit - - name: Cypress run - run: npm run test:e2e + run: pnpm build - name: Release - working-directory: lib env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: npx semantic-release@18 + run: pnpx semantic-release diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..d2c1d26 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,50 @@ +name: Run tests + +on: [push] + +env: + PNPM_CACHE_FOLDER: .pnpm-store + SKIP_INSTALL_SIMPLE_GIT_HOOKS: 1 # Skip installing simple-git-hooks + +jobs: + tests: + runs-on: ubuntu-24.04 + strategy: + matrix: + node-version: [20] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: pnpm + + - name: Cache Cypress binary + uses: actions/cache@v4 + with: + path: ~/.cache/Cypress + key: cypress-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} + + - name: Install dependencies + run: pnpm install + + - name: Build Library + run: pnpm build + + - name: Cypress run + run: pnpm run cy:components + + - name: Upload Cypress artifacts + if: failure() + uses: actions/upload-artifact@v4 + with: + name: cypress-artifacts + path: | + cypress/screenshots + cypress/videos diff --git a/.husky/commit-msg b/.husky/commit-msg deleted file mode 100755 index 2b0b740..0000000 --- a/.husky/commit-msg +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx --no -- commitlint --edit "$1" -# npx --no-install commitlint --edit - diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 36af219..0000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx lint-staged diff --git a/cypress.config.ts b/cypress.config.ts new file mode 100644 index 0000000..01921da --- /dev/null +++ b/cypress.config.ts @@ -0,0 +1,38 @@ +import { defineConfig } from 'cypress'; +import vue from '@vitejs/plugin-vue'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file +const __dirname = dirname(__filename); // get the name of the directory + +export default defineConfig({ + component: { + devServer: { + framework: 'vue', + bundler: 'vite', + viteConfig: { + plugins: [vue()], + resolve: { + alias: { + '@storyblok/vue': resolve(__dirname, './src/index.ts'), + }, + }, + /* server: { + fs: { + allow: [ + join(__dirname, '..', 'playground/vue'), + 'cypress/testing-components', + ], + }, + }, */ + }, + }, + }, + + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + }, + }, +}); diff --git a/cypress/components/index.cy.ts b/cypress/components/index.cy.ts new file mode 100644 index 0000000..e36b694 --- /dev/null +++ b/cypress/components/index.cy.ts @@ -0,0 +1,295 @@ +import Teaser from '../../playground/vue/src/components/Teaser.vue'; +import Grid from '../../playground/vue/src/components/Grid.vue'; +import Page from '../../playground/vue/src/components/Page.vue'; +import Feature from '../../playground/vue/src/components/Feature.vue'; +import MyCustomFallback from '../../playground/vue/src/components/MyCustomFallback.vue'; +import { apiPlugin, StoryblokVue } from '@storyblok/vue'; +import IframeEmbed from './testing-components/IFrameEmbed.vue'; +import { RouterLink } from 'vue-router'; +import Essential from './testing-components/Essential.vue'; +import RealApi from './testing-components/RealApi.vue'; +import RichText from './testing-components/RichText.vue'; +import { mount } from 'cypress/vue'; + +const prepare = (pluginOpts = {}, comp = Essential, globalOpts = {}) => { + mount(comp, { + global: { + plugins: [ + [ + StoryblokVue, + { + accessToken: 'OurklwV5XsDJTIE1NJaD2wtt', + ...pluginOpts, + }, + ], + ], + ...globalOpts, + }, + }); +}; + +describe('@storyblok/vue', () => { + beforeEach(() => { + cy.spy(window.console, 'log').as('log'); + cy.spy(window.console, 'error').as('error'); + delete window.storyblokRegisterEvent; + document.getElementById('storyblok-javascript-bridge')?.remove(); + }); + + describe('v-editable directive', () => { + beforeEach(() => prepare()); + + it('Gets data-blok-c and data-blok-uid attributes', () => { + cy.get('[data-test=editable]') + .should('have.attr', 'data-blok-c') + .and('equals', '{"id":12345,"uid":"fc34-uad1"}'); + + cy.get('[data-test=editable]') + .should('have.attr', 'data-blok-uid') + .and('equals', '12345-fc34-uad1'); + }); + + it('Adds \'storyblok__outline\' class to the element', () => { + cy.get('[data-test=editable]').should('have.class', 'storyblok__outline'); + }); + + it('Don\'t get data-blok-c and data-blok-uid attributes in production mode', () => { + cy.get('[data-test=editable-prod]').should( + 'not.have.attr', + 'data-blok-c', + ); + + cy.get('[data-test=editable-prod]').should( + 'not.have.attr', + 'data-blok-uid', + ); + }); + }); + + describe('Api', () => { + it('Is not loaded by default', () => { + prepare(); + cy.get('[data-test=api]').should('have.text', 'false'); + }); + + it('Is loaded correctly when using the apiPlugin', () => { + prepare({ use: [apiPlugin] }); + cy.get('[data-test=api]').should('have.text', 'true'); + }); + + it('Logs an error if no access token is provided', () => { + prepare({ + use: [apiPlugin], + accessToken: null, + apiOptions: { accessToken: null }, + }); + cy.get('@error').should('be.calledWithMatch', 'You need to provide'); + }); + }); + + describe('useStoryblok/StoryblokComponent', () => { + it('Errors when no using the apiPlugin', () => { + prepare({}, RealApi, { + components: { Teaser, Grid, Page, Feature }, + }); + cy.get('[data-test=page]').should('not.exist'); + cy.get('@error').should( + 'be.calledWithMatch', + 'You can\'t use useStoryblok', + ); + }); + + it('Doesn\'t render if components are not loaded', () => { + prepare({ use: [apiPlugin] }, RealApi); + cy.get('[data-test=page]').should('not.exist'); + cy.get('[data-test=grid]').should('not.exist'); + cy.get('[data-test=feature]').should('not.exist'); + cy.get('[data-test=teaser]').should('not.exist'); + }); + + it('Renders the expected story when loading the components', () => { + prepare({ use: [apiPlugin] }, RealApi, { + components: { Teaser, Grid, Page, Feature }, + }); + cy.get('[data-test=root]').children().should('have.length', 1); + cy.get('[data-test=page]').should('exist'); + cy.get('[data-test=grid]').should('exist'); + cy.get('[data-test=feature]').should('have.length', 2); + cy.get('[data-test=teaser]').should('exist').and('have.text', 'hello'); + }); + }); + + describe('FallbackComponent', () => { + it('Throws a console.error when the components are not loaded and enableFallbackComponent is not set', () => { + prepare({ use: [apiPlugin], enableFallbackComponent: false }, RealApi); + cy.get('@error').should( + 'be.calledWithMatch', + 'Component could not be found for blok "page"! Is it defined in main.ts as "app.component("page", page);"?', + ); + }); + + it('Renders the fallback component when the enableFallbackComponent is set to true and the component was not declared', () => { + prepare({ use: [apiPlugin], enableFallbackComponent: true }, RealApi, { + components: { Grid, Page, Feature }, + }); + + cy.get('[class=\'fallback-component\']').contains( + 'Component could not be found for blok teaser! Is it configured correctly?', + ); + cy.get('[data-test=grid]').should('exist'); + cy.get('[data-test=feature]').should('exist'); + }); + + it('Renders the custom component when the enableFallbackComponent is true, the customFallbackComponent and the component was not declared', () => { + prepare( + { + use: [apiPlugin], + enableFallbackComponent: true, + customFallbackComponent: 'MyCustomFallback', + }, + RealApi, + { + components: { Grid, Page, Feature, MyCustomFallback }, + }, + ); + + cy.get('[data-test=custom-fallback-component]').contains( + 'Custom fallback component to cover teaser', + ); + cy.get('[data-test=grid]').should('exist'); + cy.get('[data-test=feature]').should('exist'); + }); + + it('Shouldn\'t render the custom component when the enableFallbackComponent is false', () => { + prepare( + { + use: [apiPlugin], + enableFallbackComponent: false, + customFallbackComponent: 'MyCustomFallback', + }, + RealApi, + { + components: { Grid, Page, Feature, MyCustomFallback }, + }, + ); + + cy.get('[data-test=custom-fallback-component]').should('not.exist'); + cy.get('@error').should( + 'be.calledWithMatch', + 'Component could not be found for blok "teaser"! Is it defined in main.ts as "app.component("teaser", teaser);"?', + ); + }); + + it('Shouldn\'t show a console.error when the customFallbackComponent is mentioned, but the component is not registered', () => { + prepare( + { + use: [apiPlugin], + enableFallbackComponent: true, + customFallbackComponent: 'MyCustomFallback', + }, + RealApi, + { + components: { Grid, Page, Feature }, + }, + ); + + cy.get('@error').should( + 'be.calledWithMatch', + 'Is the Fallback component "MyCustomFallback" registered properly?', + ); + }); + }); + + describe('StoryblokRichText', () => { + it('Renders the rich text using StoryblokRichText component', () => { + prepare({ use: [apiPlugin] }, RichText, { + components: { Teaser, Grid, Page, Feature }, + }); + + cy.get('[data-test=root]') + .children() + .find('h1') + .should('have.text', 'Headline 1'); + }); + + it('Should render headline tags correctly', () => { + prepare({ use: [apiPlugin] }, RichText, { + components: { Teaser, Grid, Page, Feature }, + }); + + cy.get('[data-test=root]') + .children() + .find('h1') + .should('have.text', 'Headline 1'); + cy.get('[data-test=root]') + .children() + .find('h2') + .should('have.text', 'Headline 2'); + cy.get('[data-test=root]') + .children() + .find('h3') + .should('have.text', 'Headline 3'); + cy.get('[data-test=root]') + .children() + .find('h4') + .should('have.text', 'Headline 4'); + cy.get('[data-test=root]') + .children() + .find('h5') + .should('have.text', 'Headline 5'); + cy.get('[data-test=root]') + .children() + .find('h6') + .should('have.text', 'Headline 6'); + }); + + it('Should render images correctly', () => { + prepare({ use: [apiPlugin] }, RichText, { + components: { Teaser, Grid, Page, Feature }, + }); + + cy.get('[data-test=root]') + .children() + .find('img') + .should( + 'have.attr', + 'src', + 'https://a.storyblok.com/f/279818/710x528/c53330ed26/tresjs-doge.jpg', + ); + }); + + it('Should render links correctly', () => { + prepare({ use: [apiPlugin] }, RichText, { + components: { Teaser, Grid, Page, Feature }, + }); + + cy.get('[data-test=root]') + .children() + .find('a') + .should('have.attr', 'href', 'https://storyblok.com/'); + }); + + it('should render a custom iframe-embed blok component', () => { + prepare({ use: [apiPlugin] }, RichText, { + components: { IframeEmbed }, + }); + + cy.get('[data-test=root]') + .children() + .find('iframe') + .should('have.attr', 'src', 'https://storyblok.com/'); + }); + + it('should redirect internal links', () => { + prepare({ use: [apiPlugin] }, RichText, { + components: { IframeEmbed, RouterLink }, + }); + + cy.get('[data-test=root]') + .children() + .find('a') + .contains('Internal Link') + .should('have.attr', 'href', '/vue/test'); + }); + }); +}); diff --git a/lib/cypress/testing-components/Essential.vue b/cypress/components/testing-components/Essential.vue similarity index 70% rename from lib/cypress/testing-components/Essential.vue rename to cypress/components/testing-components/Essential.vue index 1212e5a..36b5e40 100644 --- a/lib/cypress/testing-components/Essential.vue +++ b/cypress/components/testing-components/Essential.vue @@ -1,14 +1,34 @@ + + - - diff --git a/playground/components/IFrameEmbed.vue b/cypress/components/testing-components/IFrameEmbed.vue similarity index 99% rename from playground/components/IFrameEmbed.vue rename to cypress/components/testing-components/IFrameEmbed.vue index 1904481..41a110f 100644 --- a/playground/components/IFrameEmbed.vue +++ b/cypress/components/testing-components/IFrameEmbed.vue @@ -6,6 +6,7 @@ defineProps({ }, }); +