Skip to content

Commit

Permalink
fix(tests): cypress tests for builder (#615)
Browse files Browse the repository at this point in the history
  • Loading branch information
spaenleh authored Jan 23, 2025
1 parent a25d9cd commit 9bf30b3
Show file tree
Hide file tree
Showing 369 changed files with 7,656 additions and 8,589 deletions.
55 changes: 48 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ on:
# Allow to manually trigger the workflow
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: false
# concurrency:
# group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
# cancel-in-progress: false

jobs:
build:
Expand Down Expand Up @@ -50,6 +50,30 @@ jobs:
env:
VITE_RECAPTCHA_SITE_KEY: 123456789

test-unit:
name: Unit Test
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4

- uses: pnpm/action-setup@v4
name: Install pnpm
with:
version: 9
run_install: false

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: "package.json"
cache: "pnpm"
cache-dependency-path: "pnpm-lock.yaml"

- name: Install dependencies
run: pnpm install

- name: Get Latest playwright version
run: echo "PLAYWRIGHT_VERSION=$(pnpm show playwright version)" >> $GITHUB_ENV
- name: Cache playwright binaries
Expand All @@ -68,7 +92,7 @@ jobs:
cypress:
name: Cypress
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 90
steps:
- name: Check out code
uses: actions/checkout@v4
Expand All @@ -85,11 +109,30 @@ jobs:
cache: "pnpm"
cache-dependency-path: "pnpm-lock.yaml"

# use the Cypress GitHub Action to run Cypress Component tests within the chrome browser
- name: Cypress run components
uses: cypress-io/github-action@v6
with:
install: true
component: true
browser: chrome
quiet: true
config-file: cypress.config.ts
cache-key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
env:
VITE_PORT: ${{ vars.VITE_PORT }}
VITE_VERSION: ${{ vars.VITE_VERSION }}
VITE_GRAASP_DOMAIN: ${{ vars.VITE_GRAASP_DOMAIN }}
VITE_GRAASP_API_HOST: ${{ vars.VITE_GRAASP_API_HOST }}
VITE_GRAASP_LIBRARY_HOST: ${{ vars.VITE_GRAASP_LIBRARY_HOST }}
VITE_SHOW_NOTIFICATIONS: ${{ vars.VITE_SHOW_NOTIFICATIONS }}
VITE_GRAASP_REDIRECTION_HOST: ${{ vars.VITE_GRAASP_REDIRECTION_HOST }}

# use the Cypress GitHub Action to run Cypress tests within the chrome browser
- name: Cypress
uses: cypress-io/github-action@v6
with:
install: true
install: false
build: pnpm build:test
# we launch the app in preview mode to avoid issues with hmr websockets from vite polluting the mocks
start: pnpm preview:test
Expand All @@ -101,9 +144,7 @@ jobs:
VITE_VERSION: ${{ vars.VITE_VERSION }}
VITE_GRAASP_DOMAIN: ${{ vars.VITE_GRAASP_DOMAIN }}
VITE_GRAASP_API_HOST: ${{ vars.VITE_GRAASP_API_HOST }}
VITE_GRAASP_PLAYER_HOST: ${{ vars.VITE_GRAASP_PLAYER_HOST }}
VITE_GRAASP_LIBRARY_HOST: ${{ vars.VITE_GRAASP_LIBRARY_HOST }}
VITE_GRAASP_ANALYZER_HOST: ${{ vars.VITE_GRAASP_ANALYZER_HOST }}
VITE_SHOW_NOTIFICATIONS: ${{ vars.VITE_SHOW_NOTIFICATIONS }}
VITE_GRAASP_REDIRECTION_HOST: ${{ vars.VITE_GRAASP_REDIRECTION_HOST }}

Expand Down
8 changes: 6 additions & 2 deletions .storybook/i18nTestInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import i18n from 'i18next';

import account from '../src/locales/en/account.json';
import auth from '../src/locales/en/auth.json';
import builder from '../src/locales/en/builder.json';
import common from '../src/locales/en/common.json';
import landing from '../src/locales/en/landing.json';
import map from '../src/locales/en/map.json';
import messages from '../src/locales/en/messages.json';
import player from '../src/locales/en/player.json';

Expand All @@ -14,7 +16,7 @@ i18n.use(initReactI18next).init({
fallbackLng: 'en',

// have a common namespace used around the full app
ns: ['auth', 'account', 'landing', 'messages', 'player'],
ns: ['auth', 'account', 'landing', 'messages', 'player', 'map', 'builder'],
defaultNS: 'translationsNS',

// debug: true,
Expand All @@ -23,7 +25,9 @@ i18n.use(initReactI18next).init({
escapeValue: false, // not needed for react!!
},

resources: { en: { landing, auth, account, messages, common, player } },
resources: {
en: { landing, auth, account, messages, common, player, map, builder },
},
});

export default i18n;
33 changes: 23 additions & 10 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
import setupCoverage from '@cypress/code-coverage/task.js';
import { defineConfig } from 'cypress';

const ENV = {
VITE_GRAASP_REDIRECTION_HOST: process.env.VITE_GRAASP_REDIRECTION_HOST,
VITE_GRAASP_DOMAIN: process.env.VITE_GRAASP_DOMAIN,
VITE_GRAASP_API_HOST: process.env.VITE_GRAASP_API_HOST,
VITE_SHOW_NOTIFICATIONS: false,
VITE_GRAASP_LIBRARY_HOST: process.env.VITE_GRAASP_LIBRARY_HOST,
};

export default defineConfig({
e2e: {
retries: {
openMode: 0,
runMode: 1,
},
// needed for redirection tests to pass
chromeWebSecurity: false,
env: {
VITE_GRAASP_DOMAIN: process.env.VITE_GRAASP_DOMAIN,
VITE_GRAASP_API_HOST: process.env.VITE_GRAASP_API_HOST,
VITE_SHOW_NOTIFICATIONS: false,
VITE_GRAASP_PLAYER_HOST: process.env.VITE_GRAASP_PLAYER_HOST,
VITE_GRAASP_ANALYZER_HOST: process.env.VITE_GRAASP_ANALYZER_HOST,
VITE_GRAASP_LIBRARY_HOST: process.env.VITE_GRAASP_LIBRARY_HOST,
VITE_GRAASP_ACCOUNT_HOST: process.env.VITE_GRAASP_ACCOUNT_HOST,
},
env: ENV,
setupNodeEvents(on, config) {
// implement node event listeners here
setupCoverage(on, config);
return config;
},
baseUrl: `http://localhost:${process.env.VITE_PORT || 3333}`,
baseUrl: `http://localhost:${process.env.VITE_PORT ?? 3333}`,
defaultCommandTimeout: 7000,
requestTimeout: 8000,
},
component: {
devServer: {
framework: 'react',
bundler: 'vite',
},
env: ENV,
},
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DEBOUNCED_TEXT_FIELD_ID } from '../../../src/config/selectors';
import DebouncedTextField, {
DEBOUNCE_MS,
} from '@/components/input/DebouncedTextField';
import { DEBOUNCED_TEXT_FIELD_ID } from '@/config/selectors';
} from '../../../src/modules/builder/components/input/DebouncedTextField';

const ON_UPDATE_SPY = 'onUpdate';
const getSpyOnUpdate = () => `@${ON_UPDATE_SPY}`;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import ThumbnailCrop from '@/components/thumbnails/ThumbnailCrop';
import {
CROP_MODAL_CONFIRM_BUTTON_ID,
IMAGE_PLACEHOLDER_FOLDER,
IMAGE_THUMBNAIL_FOLDER,
IMAGE_THUMBNAIL_UPLOADER,
REMOVE_THUMBNAIL_BUTTON,
buildDataCyWrapper,
} from '@/config/selectors';

} from '../../../src/config/selectors';
import ThumbnailCrop from '../../../src/modules/builder/components/thumbnails/ThumbnailCrop';
import {
THUMBNAIL_MEDIUM_PATH,
THUMBNAIL_SMALL_PATH,
} from '../../fixtures/thumbnails/links';
} from '../../e2e/builder/fixtures/thumbnails/links';

const ON_DELETE_SPY = 'onDelete';
const ON_UPLOAD_SPY = 'onUpload';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ import {
buildPublishAttrContainer,
buildPublishTitleAction,
buildPublishWarningIcon,
} from '@/config/selectors';
import { theme } from '@/ui/theme';

import PublicationAttributeContainer from '../../../../components/item/publish/PublicationAttributeContainer';
} from '../../../../src/config/selectors';
import PublicationAttributeContainer from '../../../../src/modules/builder/components/item/publish/PublicationAttributeContainer';
import { theme } from '../../../../src/ui/theme';

const ON_EMPTY_SPY = 'onEmptyClick';
const ON_ICON_BTN_SPY = 'onIconBtnClick';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import {
buildLibraryAddButtonHeader,
buildPublishAttrContainer,
buildPublishChip,
} from '@/config/selectors';

import PublicationChipContainer from '../../../../components/item/publish/PublicationChipContainer';
} from '../../../../src/config/selectors';
import PublicationChipContainer from '../../../../src/modules/builder/components/item/publish/PublicationChipContainer';

const ON_ADD_SPY = 'onAddClicked';
const ON_DELETE_SPY = 'onChipDelete';
Expand Down
11 changes: 6 additions & 5 deletions cypress/e2e/account/homePage.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { HttpMethod } from '@graasp/sdk';
import { formatDistanceToNow } from 'date-fns';
import { StatusCodes } from 'http-status-codes';

import { getLocalForDateFns } from '../../../src/components/langs';
import { getLocalForDateFns } from '../../../src/config/langs';
import { ACCOUNT_HOME_PATH } from '../../../src/config/paths';
import {
AVATAR_UPLOAD_ICON_ID,
Expand All @@ -20,7 +20,8 @@ import {
THUMBNAIL_MEDIUM_PATH,
} from '../../fixtures/thumbnails/links';
import { API_HOST } from '../../support/env';
import { ID_FORMAT, MemberForTest } from '../../support/utils';
import { MemberForTest } from '../../support/types';
import { ID_FORMAT } from '../../support/utils';

const { buildGetCurrentMemberRoute, buildUploadAvatarRoute } = API_ROUTES;

Expand Down Expand Up @@ -50,7 +51,7 @@ class TestHelper {
},
({ reply }) => {
if (this.currentMember.extra.hasAvatar) {
return reply({ body: this.currentMember.thumbnail });
return reply({ body: this.currentMember.thumbnails });
}
return reply({ statusCode: StatusCodes.NOT_FOUND });
},
Expand All @@ -64,7 +65,7 @@ class TestHelper {
// update avatar
this.currentMember.extra.hasAvatar = true;
// use default avatar link as thumbnail, we discard the uploaded thumbnail
this.currentMember.thumbnail = AVATAR_LINK;
this.currentMember.thumbnails = AVATAR_LINK;
return reply({ statusCode: StatusCodes.OK });
},
).as('uploadAvatar');
Expand Down Expand Up @@ -125,7 +126,7 @@ describe('Check member info', () => {
cy.get(`#${MEMBER_AVATAR_IMAGE_ID}`).should(
'have.attr',
'src',
MEMBER_WITH_AVATAR.thumbnail,
MEMBER_WITH_AVATAR.thumbnails,
);
// displays the correct member name
cy.get(`#${MEMBER_USERNAME_DISPLAY_ID}`).should(
Expand Down
4 changes: 2 additions & 2 deletions cypress/e2e/account/settings/preferences.cy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EmailFrequency } from '@graasp/sdk';
import { langs } from '@graasp/translations';

import { LANGS } from '../../../../src/config/langs';
import { ACCOUNT_SETTINGS_PATH } from '../../../../src/config/paths';
import {
PREFERENCES_ANALYTICS_SWITCH_ID,
Expand All @@ -16,7 +16,7 @@ import { CURRENT_MEMBER, MEMBERS } from '../../../fixtures/members';

describe('Display preferences', () => {
describe('Language', () => {
Object.entries(langs)
Object.entries(LANGS)
.map(([lang, expectedLabel]) => ({
lang,
expectedLabel,
Expand Down
38 changes: 38 additions & 0 deletions cypress/e2e/builder/authentication.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { PackedFolderItemFactory } from '@graasp/sdk';

import {
HEADER_APP_BAR_ID,
ITEM_MAIN_CLASS,
} from '../../../src/config/selectors';

describe('Authentication', () => {
describe('Signed Off > Redirect to sign in route', () => {
beforeEach(() => {
cy.setUpApi({ currentMember: null });
});
it('Home', () => {
cy.visit('/builder');
cy.url().should('include', '/auth/login');
});
});

describe('Signed In', () => {
const ENV = { items: [PackedFolderItemFactory()] };

beforeEach(() => {
cy.setUpApi(ENV);
});

describe('Load page correctly', () => {
it('Home', () => {
cy.visit('/builder');
cy.get(`#${HEADER_APP_BAR_ID}`).should('be.visible');
});
it('Item', () => {
cy.visit(`/builder/items/${ENV.items[0].id}`);
cy.get(`#${HEADER_APP_BAR_ID}`).should('be.visible');
cy.get(`.${ITEM_MAIN_CLASS}`).should('be.visible');
});
});
});
});
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
import {
MEMBER_VALIDATION_BANNER_CLOSE_BUTTON_ID,
MEMBER_VALIDATION_BANNER_ID,
} from '@/config/selectors';

} from '../../../src/config/selectors';
import {
LEGACY_NOT_VALIDATED_MEMBER,
NOT_VALIDATED_MEMBER,
VALIDATED_MEMBER,
} from '../fixtures/members';
} from '../../fixtures/members';

describe('Member validation banner', () => {
it('Shows banner when member is not validated', () => {
cy.setUpApi({ currentMember: NOT_VALIDATED_MEMBER });
cy.visit('/');
cy.visit('/builder');
cy.get(`#${MEMBER_VALIDATION_BANNER_ID}`).should('be.visible');
cy.get(`#${MEMBER_VALIDATION_BANNER_CLOSE_BUTTON_ID}`).click();
});

it('Does not show banner when member is validated', () => {
cy.setUpApi({ currentMember: VALIDATED_MEMBER });
cy.visit('/');
cy.visit('/builder');
cy.get(`#${MEMBER_VALIDATION_BANNER_ID}`).should('not.exist');
});

it('Does not show banner when member is legacy', () => {
cy.setUpApi({ currentMember: LEGACY_NOT_VALIDATED_MEMBER });
cy.visit('/');
cy.visit('/builder');
cy.get(`#${MEMBER_VALIDATION_BANNER_ID}`).should('not.exist');
});
});
Loading

0 comments on commit 9bf30b3

Please sign in to comment.