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"
}
}