diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..a4cba6c --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,81 @@ +image: node:latest + +cache: + paths: + - node_modules + +stages: + - lint + - test + - test:build + - deploy + +merge:test:lint: + stage: lint + script: + - npm install + - cp example.env.local .env.local + - cp example.env.local .env.test + - npm run lint + only: + - merge_requests + +merge:test:jest: + stage: test + script: + - npm install + - cp example.env.local .env.local + - cp example.env.local .env.test + - npm run test + only: + - merge_requests + +#merge:test:build: +# stage: test:build +# script: +# - npm install +# - cp example.env.local .env.local +# - cp example.env.local .env.test +# - npm run build +# only: +# - merge_requests + +test:lint: + stage: lint + script: + - npm install + - cp example.env.local .env.local + - cp example.env.local .env.test + - npm run lint + only: + - develop + - main + +test:jest: + stage: test + script: + - npm install + - cp example.env.local .env.local + - cp example.env.local .env.test + - npm run test + only: + - develop + - main + +#test:build: +# stage: test:build +# script: +# - npm install +# - cp example.env.local .env.local +# - cp example.env.local .env.test +# - npm run build +# only: +# - develop +# - main + +deploy: + stage: deploy + script: + - echo "Run deploy project" + only: + - main \ No newline at end of file diff --git a/cypress.config.js b/cypress.config.js new file mode 100644 index 0000000..3b67130 --- /dev/null +++ b/cypress.config.js @@ -0,0 +1,16 @@ +const { defineConfig } = require("cypress"); + +module.exports = defineConfig({ + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + }, + }, + + component: { + devServer: { + framework: "next", + bundler: "webpack", + }, + }, +}); diff --git a/cypress/support/commands.js b/cypress/support/commands.js new file mode 100644 index 0000000..66ea16e --- /dev/null +++ b/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) \ No newline at end of file diff --git a/cypress/support/component-index.html b/cypress/support/component-index.html new file mode 100644 index 0000000..3e16e9b --- /dev/null +++ b/cypress/support/component-index.html @@ -0,0 +1,14 @@ + + + + + + + Components App + +
+ + +
+ + \ No newline at end of file diff --git a/cypress/support/component.js b/cypress/support/component.js new file mode 100644 index 0000000..8f9154b --- /dev/null +++ b/cypress/support/component.js @@ -0,0 +1,27 @@ +// *********************************************************** +// This example support/component.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +import { mount } from 'cypress/react18' + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount() \ No newline at end of file diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js new file mode 100644 index 0000000..0e7290a --- /dev/null +++ b/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file diff --git a/jest.config.mjs b/jest.config.mjs new file mode 100644 index 0000000..5bda02f --- /dev/null +++ b/jest.config.mjs @@ -0,0 +1,17 @@ +import nextJest from 'next/jest.js' + +const createJestConfig = nextJest({ + // Provide the path to your Next.js app to load next.config.js and .env files in your test environment + dir: './', +}) + +// Add any custom config to be passed to Jest +/** @type {import('jest').Config} */ +const config = { + // Add more setup options before each test is run + setupFilesAfterEnv: ['/jest.setup.js'], + testEnvironment: 'jest-environment-jsdom', +} + +// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async +export default createJestConfig(config) \ No newline at end of file diff --git a/jest.setup.js b/jest.setup.js new file mode 100644 index 0000000..06299aa --- /dev/null +++ b/jest.setup.js @@ -0,0 +1,22 @@ +import '@testing-library/jest-dom' +import {server} from "./mocks/server"; +import mockRouter from 'next-router-mock' + +jest.mock('next/router', () => jest.requireActual('next-router-mock')) + +beforeAll(() => { + server.listen() +}) +beforeEach(() => { + localStorage.clear(); + mockRouter.query = {} + +}) + +afterEach(() => { + server.resetHandlers() +}) + +afterAll(() => { + server.close() +}) \ No newline at end of file diff --git a/mocks/AppWithProvider.jsx b/mocks/AppWithProvider.jsx new file mode 100644 index 0000000..404c839 --- /dev/null +++ b/mocks/AppWithProvider.jsx @@ -0,0 +1,13 @@ +import App from "@/pages/_app"; +import fa from "&/locales/fa/app.json" + +const translations = {fa}; +const MockAppWithProviders = ({children, locale, title, isBot}) => { + const pageProps = { + title: title || '', isBot: isBot || true, locale: locale || 'fa', messages: translations[locale || 'fa'] + } + + return ( (<>{children})} pageProps={pageProps}/>) +} + +export default MockAppWithProviders \ No newline at end of file diff --git a/mocks/handler.js b/mocks/handler.js new file mode 100644 index 0000000..eda0ea5 --- /dev/null +++ b/mocks/handler.js @@ -0,0 +1 @@ +export const handler = []; diff --git a/mocks/server.js b/mocks/server.js new file mode 100644 index 0000000..0bf9e08 --- /dev/null +++ b/mocks/server.js @@ -0,0 +1,4 @@ +import {setupServer} from "msw/node"; +import {handler} from "./handler"; + +export const server = setupServer(...handler) \ No newline at end of file diff --git a/package.json b/package.json index a560c0c..479f98d 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,11 @@ "lint": "next lint", "update": "run-script-os", "update:win32": "echo 'ok'", - "update:linux": "rm -rf .next/ && npm i && npm run build && sudo systemctl restart loan_facilities_develop_expert.service" + "update:linux": "rm -rf .next/ && npm i && npm run build && sudo systemctl restart loan_facilities_develop_expert.service", + "test": "jest", + "test:watch": "jest --watchAll", + "cypress:open": "cypress open", + "cypress:run": "cypress run" }, "dependencies": { "@emotion/react": "^11.10.6", @@ -50,7 +54,17 @@ }, "devDependencies": { "@faker-js/faker": "^7.6.0", - "eslint-config-next": "^13.3.0", + "@testing-library/jest-dom": "^6.1.4", + "@testing-library/react": "^14.0.0", + "@testing-library/user-event": "^14.5.1", + "cypress": "^13.4.0", + "eslint-config-next": "^13.5.6", + "eslint-plugin-jest-dom": "^5.1.0", + "eslint-plugin-testing-library": "^6.1.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "msw": "^2.0.3", + "next-router-mock": "^0.9.10", "run-script-os": "^1.1.6" } }