diff --git a/.dockerignore b/.dockerignore index d571957..2f03a01 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,3 @@ -*/node_modules +**/node_modules .git */dist \ No newline at end of file diff --git a/.env.dev b/.env.dev new file mode 100644 index 0000000..9bd9af8 --- /dev/null +++ b/.env.dev @@ -0,0 +1,4 @@ +TESTING=true +TESTING_USERNAME=alex +TESTING_PASSWORD=Alex1234 +SECRET_KEY=b1d2e917-17b9-4fce-9055-082dee6ec5d6 \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index afc6b85..d177747 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -63,9 +63,10 @@ module.exports = { }, overrides: [ { - files: ['**/tests/**/*.js', '**/tests/**/*.ts'], // Adjust the pattern to match your test files + files: ['**/tests/**/*.js', '**/tests/**/*.ts', '**/*.test.ts'], // Adjust the pattern to match your test files rules: { 'import/extensions': 'off', // Turn off the rule for test files + 'import/no-extraneous-dependencies': 'off', }, }, ], diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 0c2f197..7adbef8 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -12,23 +12,6 @@ jobs: uses: ./.github/workflows/ci-checks.yml secrets: inherit - code_review: - permissions: - pull-requests: write - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Code Review GPT - uses: mattzcarey/code-review-gpt@v0.1.4-alpha - with: - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - MODEL: 'gpt-3.5-turbo' - GITHUB_TOKEN: ${{ github.token }} - build: - needs: ci-checks uses: ./.github/workflows/build.yml secrets: inherit diff --git a/README.md b/README.md index 870d116..fd56c86 100644 --- a/README.md +++ b/README.md @@ -17,15 +17,22 @@ ## Development -Run everything (frontend, backend, db, swagger, quests): +Run mongoDB first: - docker compose build - docker compose up -d + docker compose -f docker-compose.dev.yml up -d db + +The db will automatically restarts by Docker. + +Build up dependencies: + + yarn build:deps + +Run dev server (frontend, backend): + + yarn dev If you want to enable social login, you should have OAuth client token in a `.env` file: - docker compose --env-file .env up -d - ### Build Quest Images In each quest folder, there is a `game.yml` file, which is the quest definition. And a optional `Dockerfile` to overwrite the base image. If you want to include additional files, put them in a `home` folder. The files in `home` will **not** be copied to the image automatically, you have to copy them in the `Dockerfile`. @@ -144,4 +151,3 @@ connect to other host: list sessions: yarn cli list - \ No newline at end of file diff --git a/app/Dockerfile b/app/Dockerfile index f8806ac..506854c 100644 --- a/app/Dockerfile +++ b/app/Dockerfile @@ -7,7 +7,7 @@ COPY packages/file-graph/package.json ./packages/file-graph/package.json COPY packages/utils/package.json ./packages/utils/package.json COPY packages/constants/package.json ./packages/constants/package.json COPY app/package.json ./app/package.json -RUN yarn install +RUN yarn install # Dev stage FROM base as dev diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 82b34a6..ec86378 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -74,6 +74,7 @@ services: db: image: mongo + restart: always networks: - internal ports: diff --git a/docker-compose.testing.yml b/docker-compose.testing.yml index 18f0f97..5c67018 100644 --- a/docker-compose.testing.yml +++ b/docker-compose.testing.yml @@ -12,6 +12,7 @@ services: - BASE_URL=http://app-test - TESTING_USERNAME=alex - TESTING_PASSWORD=Alex1234 + # - DEBUG=cypress:* depends_on: - app-test @@ -23,8 +24,9 @@ services: target: prod networks: internal: - ports: - - 5173:80 + # Only open the port for debugging + # ports: + # - 5173:80 depends_on: - backend @@ -71,8 +73,8 @@ services: - MONGO_USER=user - MONGO_PASS=user-password - MONGO_DB=odyssey-test - ports: - - 27017:27017 + # ports: + # - 27017:27017 base: image: linuxodyssey/quest-base diff --git a/package.json b/package.json index 1f8d8f7..04954b1 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "build:quests": "yarn workspace server build:quests" }, "devDependencies": { + "@jest/globals": "^29.7.0", "@types/jest": "^29.5.12", "@types/node": "^20.10.4", "@typescript-eslint/eslint-plugin": "^6.14.0", diff --git a/packages/analytics/.env.dev b/packages/analytics/.env.dev new file mode 100644 index 0000000..1a17b26 --- /dev/null +++ b/packages/analytics/.env.dev @@ -0,0 +1,2 @@ +ADMIN_USERNAME=alex +ADMIN_PASSWORD=Alex1234 \ No newline at end of file diff --git a/packages/analytics/Dockerfile b/packages/analytics/Dockerfile index f204e34..15d1b22 100644 --- a/packages/analytics/Dockerfile +++ b/packages/analytics/Dockerfile @@ -1,11 +1,10 @@ FROM node:20-alpine as build WORKDIR /app -COPY ./package.json yarn.lock ./ +COPY ./package.json yarn.lock tsconfig.json ./ COPY packages/analytics/package.json ./packages/analytics/package.json COPY packages/models/package.json ./packages/models/package.json -RUN yarn set version berry -RUN yarn install +RUN yarn install --frozen-lockfile ENV HOST=0.0.0.0 ENV PORT=3001 EXPOSE 3001 diff --git a/packages/analytics/nodemon.json b/packages/analytics/nodemon.json index 0cd3700..ec52edb 100644 --- a/packages/analytics/nodemon.json +++ b/packages/analytics/nodemon.json @@ -1,6 +1,6 @@ { - "watch": ["src"], + "watch": ["src", "views"], "ext": "ts,handlebars,js", "ignore": ["src/**/*.spec.ts"], - "exec": "node --loader ts-node/esm src/index.ts" + "exec": "node --loader ts-node/esm src/index.js" } diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 85c1389..f1507fc 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -13,14 +13,19 @@ }, "dependencies": { "@linux-odyssey/models": "*", + "dotenv": "^16.4.5", "express": "^4.18.2", "express-basic-auth": "^1.2.1", "express-handlebars": "^7.1.2", "mongoose": "^8.0.3" }, "devDependencies": { + "@swc/core": "^1.4.2", + "@swc/helpers": "^0.5.6", + "@types/express": "^4.17.21", "@types/node": "^20.11.20", "nodemon": "^3.1.0", + "regenerator-runtime": "^0.14.1", "ts-node": "^10.9.2", "typescript": "^5.3.3" } diff --git a/packages/analytics/src/config.ts b/packages/analytics/src/config.ts index bece519..850cfa8 100644 --- a/packages/analytics/src/config.ts +++ b/packages/analytics/src/config.ts @@ -1,3 +1,9 @@ +import dotenv from 'dotenv' + +if (process.env.NODE_ENV !== 'production') { + dotenv.config({ path: '.env.dev' }) +} + function getOrFailed(key: string): string { if (!process.env[key]) { throw new Error(`Missing required environment variable: ${key}`) @@ -16,13 +22,13 @@ interface Config { const config: Config = { host: process.env.HOST || 'localhost', - port: process.env.PORT ? parseInt(process.env.PORT) : 3001, + port: process.env.PORT ? parseInt(process.env.PORT, 10) : 3001, db: process.env.MONGO_URL || 'mongodb://localhost:27017/odyssey-test', - username: 'a' || getOrFailed('ADMIN_USERNAME'), - password: 'a' || getOrFailed('ADMIN_PASSWORD'), + username: getOrFailed('ADMIN_USERNAME'), + password: getOrFailed('ADMIN_PASSWORD'), baseUrl: process.env.BASE_URL || - `http://${process.env.HOST || 'localhost'}:${process.env.PORT ? parseInt(process.env.PORT) : 3001}`, + `http://${process.env.HOST || 'localhost'}:${process.env.PORT ? parseInt(process.env.PORT, 10) : 3001}`, } export default config diff --git a/packages/analytics/src/controllers/quests.ts b/packages/analytics/src/controllers/quests.ts index ba135cc..047f3ce 100644 --- a/packages/analytics/src/controllers/quests.ts +++ b/packages/analytics/src/controllers/quests.ts @@ -1,4 +1,4 @@ -import { questList } from '../models/quests.ts' +import { questList } from '../models/quests.js' // eslint-disable-next-line import/prefer-default-export export async function questListController(req: any, res: any) { const quests = await questList() diff --git a/packages/analytics/src/controllers/users.ts b/packages/analytics/src/controllers/users.ts index a385385..d651488 100644 --- a/packages/analytics/src/controllers/users.ts +++ b/packages/analytics/src/controllers/users.ts @@ -1,5 +1,10 @@ +<<<<<<< HEAD import Pagination from '../models/pagination.ts' import { userList, userDetail, idToUser } from '../models/users.js' +======= +import Pagination from '../models/pagination.js' +import { userList } from '../models/users.js' +>>>>>>> bb4a11b20c8fdad8459ac3b7a0fdb8d9d9221e31 export async function userListController(req: any, res: any) { const { nextKey, order } = req.query @@ -20,6 +25,7 @@ export async function userListController(req: any, res: any) { res.status(500).send('Error fetching user data') } } +<<<<<<< HEAD export async function userDetailController(req: any, res: any) { const { id } = req.params const sessions = await userDetail(id) @@ -31,3 +37,5 @@ export async function userDetailController(req: any, res: any) { res.status(500).send('Error fetching user data') } } +======= +>>>>>>> bb4a11b20c8fdad8459ac3b7a0fdb8d9d9221e31 diff --git a/packages/analytics/tsconfig.json b/packages/analytics/tsconfig.json index ebc4140..2580aa7 100644 --- a/packages/analytics/tsconfig.json +++ b/packages/analytics/tsconfig.json @@ -1,7 +1,6 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "allowJs": true, "rootDir": "src", "outDir": "./dist", "esModuleInterop": true, @@ -9,5 +8,8 @@ "allowImportingTsExtensions": true }, "include": ["src"], - "exclude": ["node_modules", "dist"] + "exclude": ["node_modules", "dist"], + "ts-node": { + "swc": true + } } diff --git a/packages/file-graph/tests/file.test.ts b/packages/file-graph/tests/file.test.ts index 0524f93..57eba95 100644 --- a/packages/file-graph/tests/file.test.ts +++ b/packages/file-graph/tests/file.test.ts @@ -1,4 +1,5 @@ -import File from '../src/file' +import { describe, test, expect } from '@jest/globals' +import File from '../src/file.js' describe('File', () => { let file: File diff --git a/packages/file-graph/tests/fileGraph.test.ts b/packages/file-graph/tests/fileGraph.test.ts index fd21202..c9ff417 100644 --- a/packages/file-graph/tests/fileGraph.test.ts +++ b/packages/file-graph/tests/fileGraph.test.ts @@ -1,3 +1,4 @@ +import { describe, test, expect } from '@jest/globals' import FileGraph from '../src/fileGraph.js' import FileNode from '../src/fileNode.js' diff --git a/packages/file-graph/tests/fileNode.test.ts b/packages/file-graph/tests/fileNode.test.ts index 3ccb3e1..14c6818 100644 --- a/packages/file-graph/tests/fileNode.test.ts +++ b/packages/file-graph/tests/fileNode.test.ts @@ -1,3 +1,4 @@ +import { describe, test, expect } from '@jest/globals' import { DuplicateItemError, ParentNotExistsError } from '../src/errors.js' import FileNode from '../src/fileNode.js' import { FileObject } from '../src/file.js' diff --git a/packages/utils/tests/auth.test.ts b/packages/utils/tests/auth.test.ts index 28593f7..84eff27 100644 --- a/packages/utils/tests/auth.test.ts +++ b/packages/utils/tests/auth.test.ts @@ -1,3 +1,4 @@ +import { test, expect } from '@jest/globals' import { isValidEmail, isValidUsername } from '../src/auth.js' test('check valid username', () => { diff --git a/packages/utils/tests/commands.test.ts b/packages/utils/tests/commands.test.ts index 7730678..77d02d1 100644 --- a/packages/utils/tests/commands.test.ts +++ b/packages/utils/tests/commands.test.ts @@ -1,3 +1,4 @@ +import { describe, it, expect } from '@jest/globals' import { buildFileCheckCmd, File } from '../src/commands.js' describe('buildFileCheckCmd function', () => { diff --git a/packages/utils/tests/dag.test.ts b/packages/utils/tests/dag.test.ts index ff631c0..fbe860d 100644 --- a/packages/utils/tests/dag.test.ts +++ b/packages/utils/tests/dag.test.ts @@ -1,3 +1,4 @@ +import { describe, it, expect } from '@jest/globals' import DAG from '../src/dag.js' describe('dag layers', () => { diff --git a/server/src/config.ts b/server/src/config.ts index adc0863..96377a1 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -4,6 +4,9 @@ import { get } from './utils/env.js' // Import dotenv and load ../.env dotenv.config({ path: '../.env' }) +if (process.env.NODE_ENV !== 'production') { + dotenv.config({ path: '../.env.dev' }) +} function getTrustProxies(key: string): string[] { const value = process.env[key] diff --git a/server/src/containers/docker.ts b/server/src/containers/docker.ts index 8ac2d03..e279793 100644 --- a/server/src/containers/docker.ts +++ b/server/src/containers/docker.ts @@ -27,7 +27,7 @@ export function createContainer(name, questId) { const { hostPwd, mountQuest } = config.docker if (!config.isProduction && hostPwd && mountQuest === questId) { logger.info('Mounting quest folder', mountQuest) - option.HostConfig.Binds = [ + option.HostConfig!.Binds = [ `${hostPwd.replace(/\\/g, '/')}/quests/${mountQuest}/home:/home/commander`, `${hostPwd.replace(/\\/g, '/')}/packages/container:/usr/local/lib/container`, ] diff --git a/tests/Dockerfile b/tests/Dockerfile index 1dc0d4a..d5c96d2 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -3,7 +3,7 @@ FROM cypress/browsers WORKDIR /e2e COPY package.json yarn.lock ./ COPY tests/package.json ./tests/package.json -RUN yarn install +RUN yarn install --frozen-lockfile COPY quests ./quests COPY tests ./tests diff --git a/tests/cypress.config.js b/tests/cypress.config.ts similarity index 69% rename from tests/cypress.config.js rename to tests/cypress.config.ts index b2bb72e..ce86fe3 100644 --- a/tests/cypress.config.js +++ b/tests/cypress.config.ts @@ -1,20 +1,27 @@ -const { defineConfig } = require('cypress') -const process = require('process') -require('dotenv').config({ path: '../.env' }) +import { defineConfig } from 'cypress' +import process from 'process' +import dotenv from 'dotenv' +import fs from 'fs' // Import fs module + +dotenv.config({ path: '../.env.dev' }) +dotenv.config({ path: '../.env' }) const getConfig = (key, defaultValue) => { return process.env[key] || defaultValue } const getOrFail = (key) => { - const value = getConfig(key) + const value = getConfig(key, null) if (!value) { throw new Error(`Missing required environment variable ${key}`) } return value } -module.exports = defineConfig({ +// Check if the .env file exists +const EnableoAuth = fs.existsSync('../.env') + +export default defineConfig({ e2e: { baseUrl: getConfig('BASE_URL', 'http://localhost:5173'), viewportWidth: 1920, @@ -28,13 +35,13 @@ module.exports = defineConfig({ defaultAccount: getOrFail('TESTING_USERNAME'), defaultPassword: getOrFail('TESTING_PASSWORD'), isCHVersion: true, + EnableoAuth, // Add the EnableoAuth variable here // google_username: process.env.GOOGLE_USERNAME, // google_password: process.env.GOOGLE_PASSWORD, // google_client_id: process.env.GOOGLE_CLIENT_ID, - // google_client_secret: process.env.GOOGLE_CLIENT_SECRET, + // github_username: process.env.GITHUB_USERNAME, // github_password: process.env.GITHUB_PASSWORD, // github_client_id: process.env.GITHUB_CLIENT_ID, - // github_client_secret: process.env.GITHUB_CLIENT_SECRET, }, }) diff --git a/tests/cypress/e2e/UItests.cy.js b/tests/cypress/e2e/UItests.cy.ts similarity index 85% rename from tests/cypress/e2e/UItests.cy.js rename to tests/cypress/e2e/UItests.cy.ts index c2ecfd7..1ea8646 100644 --- a/tests/cypress/e2e/UItests.cy.js +++ b/tests/cypress/e2e/UItests.cy.ts @@ -1,4 +1,3 @@ -/// export default function checkLoginUI() { cy.get('#title').should('contain', 'Linux Odyssey').and('be.visible') cy.CheckPlaceholder('#password', '密碼', 'Password') @@ -37,17 +36,19 @@ describe('example helloworld app', () => { cy.CheckTextElement('#SwitchtoRegister', '註冊', 'Sign up') }) it('Check social account UI', () => { - cy.CheckTextElement( - '#GoogleLogin', - '以 Google 繼續', - 'Continue with Google' - ) - cy.CheckTextElement('#or', '或', 'or') - cy.CheckTextElement( - '#GitHubLogin', - '以 GitHub 繼續', - 'Continue with GitHub' - ) + if (Cypress.env('EnableoAuth')) { + cy.CheckTextElement( + '#GoogleLogin', + '以 Google 繼續', + 'Continue with Google' + ) + cy.CheckTextElement('#or', '或', 'or') + cy.CheckTextElement( + '#GitHubLogin', + '以 GitHub 繼續', + 'Continue with GitHub' + ) + } }) it('Check login fail', () => { cy.LoginWithPassword('dddd', '123456') @@ -96,20 +97,18 @@ describe('example helloworld app', () => { cy.CheckTextElement('#tasks', '任務', 'Tasks:') }) it('Check Terminal', () => { - cy.get('#terminal', { timeout: 20000 }).within(($terminal) => { - cy.get($terminal).should('be.visible') - cy.get('svg[data-icon="terminal"]').should('be.visible') - cy.CheckTextElement('#Terminal', '終端機', 'Terminal') - cy.get('@Terminaltextbox') - .should('be.visible') - .and('contain', 'commander:~ $') - }) + // cy.get('#terminal', { timeout: 20000 }).within(($terminal) => { + // cy.get($terminal).should('be.visible') + cy.get('#terminal', { timeout: 20000 }).should('be.visible') + cy.get('svg[data-icon="terminal"]').should('be.visible') + cy.CheckTextElement('#Terminal', '終端機', 'Terminal') + cy.get('@Terminaltextbox') + .should('be.visible') + .and('contain', 'commander:~ $') }) it('Check Hint Part', () => { - cy.get('#hint', { timeout: 20000 }).within(($hint) => { - cy.get($hint).should('be.visible') - cy.get('svg[data-icon="lightbulb"]').should('be.visible') - }) + cy.get('#hint', { timeout: 20000 }).should('be.visible') + cy.get('svg[data-icon="lightbulb"]').should('be.visible') cy.CheckTextElement('#hint', '提示', 'Hint') }) it('Check File TreeChart', () => { diff --git a/tests/cypress/e2e/completeQuests.cy.js b/tests/cypress/e2e/completeQuests.cy.ts similarity index 96% rename from tests/cypress/e2e/completeQuests.cy.js rename to tests/cypress/e2e/completeQuests.cy.ts index 3ef0aab..57ba8e2 100644 --- a/tests/cypress/e2e/completeQuests.cy.js +++ b/tests/cypress/e2e/completeQuests.cy.ts @@ -1,4 +1,3 @@ -/// describe('Complete quests with only commands', () => { beforeEach(() => { cy.PrepareForGame() diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.ts similarity index 70% rename from tests/cypress/support/commands.js rename to tests/cypress/support/commands.ts index 9428779..b77cd88 100644 --- a/tests/cypress/support/commands.js +++ b/tests/cypress/support/commands.ts @@ -1,7 +1,38 @@ +/* eslint-disable no-undef */ +/* eslint-disable no-unused-vars */ +/// import '@testing-library/cypress/add-commands' +declare const expect: Chai.ExpectStatic +declare global { + namespace Cypress { + interface Chainable { + LoginWithPassword(username: string, password: string): Chainable + PrepareForGame(): Chainable + InitTerminal(): Chainable + typeInCommand(command: string): Chainable + getQuestInfo(id: string): Chainable> + checkHint(index: number, total: number): Chainable // 修改類型 + checkTaskInit(): Chainable + waitUntilActive(last?: boolean): Chainable // 注意小寫boolean,並且變量名應該是小寫 + checkPending(): Chainable + CompleteStageWithCommands(stagename: string): Chainable + CheckTextElement( + id: string, + chText: string, + enText: string + ): Chainable + CheckPlaceholder( + id: string, + chText: string, + enText: string + ): Chainable + CheckTreeElement(element: string): Chainable + } + } +} Cypress.Commands.add('LoginWithPassword', (username, password) => { - cy.clearAllCookies({ domain: null }) + cy.clearAllCookies() cy.visit('/login') cy.get('#username').type(username) cy.get('#password').type(password) @@ -10,7 +41,7 @@ Cypress.Commands.add('LoginWithPassword', (username, password) => { Cypress.Commands.add('PrepareForGame', () => { cy.visit('/') // make sure the login page is loaded - cy.url().should('satisfy', (elements) => { + cy.url().should('satisfy', (elements: string) => { const text = elements return text.includes('login') || text.includes('register') }) @@ -70,9 +101,9 @@ Cypress.Commands.add('waitUntilActive', (last = false) => { return } if (value === 'pending' && !last) { - cy.log(last) + cy.log(`${last}`) cy.typeInCommand('{enter}') - cy.waitUntilActive() + cy.waitUntilActive(last) // Pass `last` parameter } }) }) @@ -90,8 +121,7 @@ Cypress.Commands.add('CompleteStageWithCommands', (stagename) => { cy.CheckTextElement('#reset', '重來', 'Reset').click() cy.checkTaskInit() cy.InitTerminal() - cy.readFile(`../quests/${stagename}/answer.sh`, 'utf-8').as('answers') - cy.get('@answers').then((answers) => { + cy.readFile(`../quests/${stagename}/answer.sh`, 'utf-8').then((answers) => { const answerarr = answers.split('\n') for (const element of answerarr) { cy.typeInCommand(`${element}{enter}`) @@ -109,13 +139,11 @@ Cypress.Commands.add('CompleteStageWithCommands', (stagename) => { }) }) Cypress.Commands.add('CheckTextElement', (id, chText, enText) => { - cy.get(id, { timeout: 50000 }).within(($element) => { - if (Cypress.env('isCHVersion')) { - cy.get($element).should('contain', chText).and('be.visible') - } else { - cy.get($element).should('contain', enText).and('be.visible') - } - }) + if (Cypress.env('isCHVersion')) { + cy.get(id, { timeout: 50000 }).should('contain', chText).and('be.visible') + } else { + cy.get(id, { timeout: 50000 }).should('contain', enText).and('be.visible') + } }) Cypress.Commands.add('CheckPlaceholder', (id, chText, enText) => { cy.get(id) diff --git a/tests/cypress/support/e2e.js b/tests/cypress/support/e2e.ts similarity index 100% rename from tests/cypress/support/e2e.js rename to tests/cypress/support/e2e.ts diff --git a/tests/package.json b/tests/package.json index 18332d0..885c84b 100644 --- a/tests/package.json +++ b/tests/package.json @@ -3,14 +3,20 @@ "version": "1.0.0", "private": true, "main": "index.js", + "type": "commonjs", "license": "MIT", "scripts": { - "test": "TESTING_USERNAME=alex TESTING_PASSWORD=Alex1234 cypress run", - "test:open": "TESTING_USERNAME=alex TESTING_PASSWORD=Alex1234 cypress open" + "test": "yarn cypress run", + "test:open": "yarn cypress open" }, "dependencies": { "@testing-library/cypress": "^10.0.1", "cypress": "^13.5.1", - "dotenv": "^16.3.1" + "dotenv": "^16.3.1", + "ts-node": "^10.9.2" + }, + "devDependencies": { + "@types/dotenv": "^8.2.0", + "typescript": "^5.3.3" } } diff --git a/tests/tsconfig.json b/tests/tsconfig.json new file mode 100644 index 0000000..6f9a664 --- /dev/null +++ b/tests/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "outDir": "dist", + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress", "node", "@testing-library/cypress"], + "esModuleInterop": true + }, + "include": ["**/*.ts"], + "exclude": ["dist"] +} diff --git a/yarn.lock b/yarn.lock index 01fe85a..7fc59c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -913,6 +913,92 @@ resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== +"@swc/core-darwin-arm64@1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.2.tgz#3b5677c5b9c5a7a91d953b96cd603c94064e2835" + integrity sha512-1uSdAn1MRK5C1m/TvLZ2RDvr0zLvochgrZ2xL+lRzugLlCTlSA+Q4TWtrZaOz+vnnFVliCpw7c7qu0JouhgQIw== + +"@swc/core-darwin-x64@1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.4.2.tgz#bbc8bbf420389b12541151255a50f319cc17ef96" + integrity sha512-TYD28+dCQKeuxxcy7gLJUCFLqrwDZnHtC2z7cdeGfZpbI2mbfppfTf2wUPzqZk3gEC96zHd4Yr37V3Tvzar+lQ== + +"@swc/core-linux-arm-gnueabihf@1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.2.tgz#aa9a18f130820717df08c9dd882043fc47e8d35a" + integrity sha512-Eyqipf7ZPGj0vplKHo8JUOoU1un2sg5PjJMpEesX0k+6HKE2T8pdyeyXODN0YTFqzndSa/J43EEPXm+rHAsLFQ== + +"@swc/core-linux-arm64-gnu@1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.2.tgz#5ef1de0ca7cc3a034aa3a1c3c1794b78e6ca207e" + integrity sha512-wZn02DH8VYPv3FC0ub4my52Rttsus/rFw+UUfzdb3tHMHXB66LqN+rR0ssIOZrH6K+VLN6qpTw9VizjyoH0BxA== + +"@swc/core-linux-arm64-musl@1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.2.tgz#5dfd2a8c0483770a307de0ccb6019a082ff0d902" + integrity sha512-3G0D5z9hUj9bXNcwmA1eGiFTwe5rWkuL3DsoviTj73TKLpk7u64ND0XjEfO0huVv4vVu9H1jodrKb7nvln/dlw== + +"@swc/core-linux-x64-gnu@1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.2.tgz#314aa76b7c1208e315e3156ab57b7188fb605bc2" + integrity sha512-LFxn9U8cjmYHw3jrdPNqPAkBGglKE3tCZ8rA7hYyp0BFxuo7L2ZcEnPm4RFpmSCCsExFH+LEJWuMGgWERoktvg== + +"@swc/core-linux-x64-musl@1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.2.tgz#b2b226657f6a8d48f561cb3dbe2d414cfbafe467" + integrity sha512-dp0fAmreeVVYTUcb4u9njTPrYzKnbIH0EhH2qvC9GOYNNREUu2GezSIDgonjOXkHiTCvopG4xU7y56XtXj4VrQ== + +"@swc/core-win32-arm64-msvc@1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.2.tgz#582f79fa328ce0f426ab8313b3d881e7315fab2f" + integrity sha512-HlVIiLMQkzthAdqMslQhDkoXJ5+AOLUSTV6fm6shFKZKqc/9cJvr4S8UveNERL9zUficA36yM3bbfo36McwnvQ== + +"@swc/core-win32-ia32-msvc@1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.2.tgz#15c8289e1c18857f79b9b888100ab1f871bf58f6" + integrity sha512-WCF8faPGjCl4oIgugkp+kL9nl3nUATlzKXCEGFowMEmVVCFM0GsqlmGdPp1pjZoWc9tpYanoXQDnp5IvlDSLhA== + +"@swc/core-win32-x64-msvc@1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.2.tgz#c999ca7b68124d058b40a1431cdd6f56779670d5" + integrity sha512-oV71rwiSpA5xre2C5570BhCsg1HF97SNLsZ/12xv7zayGzqr3yvFALFJN8tHKpqUdCB4FGPjoP3JFdV3i+1wUw== + +"@swc/core@^1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.4.2.tgz#310b0d5e93e47ca72f54150c8f9efcb434c39b17" + integrity sha512-vWgY07R/eqj1/a0vsRKLI9o9klGZfpLNOVEnrv4nrccxBgYPjcf22IWwAoaBJ+wpA7Q4fVjCUM8lP0m01dpxcg== + dependencies: + "@swc/counter" "^0.1.2" + "@swc/types" "^0.1.5" + optionalDependencies: + "@swc/core-darwin-arm64" "1.4.2" + "@swc/core-darwin-x64" "1.4.2" + "@swc/core-linux-arm-gnueabihf" "1.4.2" + "@swc/core-linux-arm64-gnu" "1.4.2" + "@swc/core-linux-arm64-musl" "1.4.2" + "@swc/core-linux-x64-gnu" "1.4.2" + "@swc/core-linux-x64-musl" "1.4.2" + "@swc/core-win32-arm64-msvc" "1.4.2" + "@swc/core-win32-ia32-msvc" "1.4.2" + "@swc/core-win32-x64-msvc" "1.4.2" + +"@swc/counter@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/helpers@^0.5.6": + version "0.5.6" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.6.tgz#d16d8566b7aea2bef90d059757e2d77f48224160" + integrity sha512-aYX01Ke9hunpoCexYAgQucEpARGQ5w/cqHFrIR+e9gdKb1QWTsVJuTJ2ozQzIAxLyRQe/m+2RqzkyOOGiMKRQA== + dependencies: + tslib "^2.4.0" + +"@swc/types@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.5.tgz#043b731d4f56a79b4897a3de1af35e75d56bc63a" + integrity sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw== + "@testing-library/cypress@^10.0.1": version "10.0.1" resolved "https://registry.yarnpkg.com/@testing-library/cypress/-/cypress-10.0.1.tgz#15abae0edb83237316ec6d07e152b71a50b38387" @@ -1043,6 +1129,13 @@ "@types/docker-modem" "*" "@types/node" "*" +"@types/dotenv@^8.2.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@types/dotenv/-/dotenv-8.2.0.tgz#5cd64710c3c98e82d9d15844375a33bf1b45d053" + integrity sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw== + dependencies: + dotenv "*" + "@types/express-serve-static-core@^4.17.33": version "4.17.43" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz#10d8444be560cb789c4735aea5eac6e5af45df54" @@ -1169,6 +1262,13 @@ dependencies: undici-types "~5.26.4" +"@types/node@^20.11.20": + version "20.11.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.21.tgz#ad67e65652f7be15686e2df87a38076a81c5e9c5" + integrity sha512-/ySDLGscFPNasfqStUuWWPfL78jompfIoVzLJPVVAHBh6rpG68+pI2Gk+fNLeI8/f1yPYL4s46EleVIc20F1Ow== + dependencies: + undici-types "~5.26.4" + "@types/oauth@*": version "0.9.4" resolved "https://registry.yarnpkg.com/@types/oauth/-/oauth-0.9.4.tgz#dcbab5efa2f34f312b915f80685760ccc8111e0a" @@ -2777,7 +2877,7 @@ dompurify@^3.0.6: resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.9.tgz#b3f362f24b99f53498c75d43ecbd784b0b3ad65e" integrity sha512-uyb4NDIvQ3hRn6NiC+SIFaP4mJ/MdXlvtunaqK9Bn6dD3RuB/1S/gasEjDHD8eiaqdSael2vBv+hOs7Y+jhYOQ== -dotenv@^16.3.1, dotenv@^16.4.1: +dotenv@*, dotenv@^16.3.1, dotenv@^16.4.1, dotenv@^16.4.5: version "16.4.5" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== @@ -5366,6 +5466,22 @@ nodemon@^3.0.1: touch "^3.1.0" undefsafe "^2.0.5" +nodemon@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.0.tgz#ff7394f2450eb6a5e96fe4180acd5176b29799c9" + integrity sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA== + dependencies: + chokidar "^3.5.2" + debug "^4" + ignore-by-default "^1.0.1" + minimatch "^3.1.2" + pstree.remy "^1.1.8" + semver "^7.5.3" + simple-update-notifier "^2.0.0" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.5" + nopt@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" @@ -5988,7 +6104,7 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -regenerator-runtime@^0.14.0: +regenerator-runtime@^0.14.0, regenerator-runtime@^0.14.1: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== @@ -6833,7 +6949,7 @@ tslib@2.3.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== -tslib@^2.1.0, tslib@^2.6.2: +tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==