├── .eslintrc.js
├── .github
└── workflows
│ └── ci.yaml
├── .gitignore
├── .prettierignore
├── .prettierrc
├── jest.config.js
├── package-lock.json
├── package.json
├── readme.md
├── src
├── app
│ ├── index.html
│ ├── index.ts
│ └── readme.md
├── index.ts
└── models
│ ├── room
│ ├── readme.md
│ ├── room.test.ts
│ └── room.ts
│ └── user
│ ├── readme.md
│ ├── user.test.ts
│ └── user.ts
└── tsconfig.json
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | es2021: true,
4 | node: true
5 | },
6 | extends: [
7 | 'standard',
8 | 'prettier'
9 | ],
10 | parser: '@typescript-eslint/parser',
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | sourceType: 'module'
14 | },
15 | plugins: [
16 | 'import',
17 | '@typescript-eslint',
18 | 'prettier'
19 | ],
20 | rules: {
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: pull_request
4 |
5 | jobs:
6 | verify:
7 | name: Game Case
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Checkout repository
11 | uses: actions/checkout@v2
12 | - name: Setup node
13 | uses: actions/setup-node@v2
14 | with:
15 | node-version: '15.x'
16 | - name: Install packages
17 | working-directory: src
18 | run: npm ci
19 | - name: Formatting, linting, tsc and tests
20 | working-directory: src
21 | run: |
22 | npm run prettier:check
23 | npm run lint
24 | npm run test
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | coverage
4 | .DS_Store
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | build/
3 | dist/
4 | package-lock.json
5 | .eslintrc.js
6 | .prettierrc
7 | tsconfig.json
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "tabWidth": 2,
4 | "trailingComma": "none",
5 | "printWidth": 100,
6 | "overrides": [
7 | {
8 | "files":"*.ts",
9 | "options": {
10 | "parser":"typescript"
11 | }
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'ts-jest',
3 | testEnvironment: 'node'
4 | }
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rooms",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "dist/index.js",
6 | "typings": "dist/index.d.ts",
7 | "scripts": {
8 | "build": "tsc",
9 | "test": "jest",
10 | "test:watch": "jest --verbose --watchAll --no-cache --runInBand",
11 | "tsc:check": "tesc --noEmit",
12 | "lint": "eslint src/**/*.ts",
13 | "prettier:check": "prettier --check src/**/*.ts",
14 | "prettier:fix": "prettier --write src/**/*.ts"
15 | },
16 | "author": "",
17 | "license": "ISC",
18 | "dependencies": {
19 | "express": "^4.17.1",
20 | "socket.io": "^4.0.1"
21 | },
22 | "devDependencies": {
23 | "@types/express": "^4.17.11",
24 | "@types/jest": "^26.0.22",
25 | "@types/node": "^14.14.41",
26 | "@types/socket.io": "^2.1.13",
27 | "@typescript-eslint/eslint-plugin": "^4.22.0",
28 | "@typescript-eslint/parser": "^4.22.0",
29 | "eslint": "^7.24.0",
30 | "eslint-config-prettier": "^8.3.0",
31 | "eslint-config-standard": "^16.0.2",
32 | "eslint-plugin-import": "^2.22.1",
33 | "eslint-plugin-node": "^11.1.0",
34 | "eslint-plugin-prettier": "^3.4.0",
35 | "eslint-plugin-promise": "^4.3.1",
36 | "faker": "^5.5.3",
37 | "husky": "^4.3.0",
38 | "jest": "^26.6.3",
39 | "lint-staged": "^11.0.0",
40 | "prettier": "^2.2.1",
41 | "sinon": "^10.0.0",
42 | "ts-jest": "^26.5.5",
43 | "ts-node": "^9.1.1",
44 | "typescript": "^4.2.4"
45 | },
46 | "lint-staged": {
47 | "src/**/*.ts": [
48 | "npm run prettier:fix",
49 | "npm run lint",
50 | "git add"
51 | ]
52 | },
53 | "husky": {
54 | "hooks": {
55 | "pre-commit": "lint-staged && npm run test"
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # TDD Game Case
2 |
3 | # Install
4 |
5 | ```bash
6 | git clone git@github.com:findmentor-network/javascript-workshop-homework
7 | cd javascript-workshop-homework
8 | npm install
9 | ```
10 |
11 | # Run test runner
12 |
13 | ```bash
14 | npm run test -- --coverage
15 | ```
16 |
17 |
18 | # Step 1
19 |
20 | Every model has own methods and tests as dir.
21 | Write tests and open a pull request.
22 | Do not implement any kind of code first
23 |
24 | # Step 2
25 |
26 | If the tests are done, you are ready to implement.
27 | Implement the user class.
28 |
29 | # Step 3
30 |
31 | Implement the room class.
32 |
33 | # Step 4
34 |
35 | Write a dummy socket.io code and use that classes
36 |
37 | # Step 5
38 |
39 | Write a dummy html and js code and use that socket.io backend.
40 |
41 |
--------------------------------------------------------------------------------
/src/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Game
8 |
9 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/src/app/index.ts:
--------------------------------------------------------------------------------
1 | // This file represents the backend project.
2 | console.log('Backend');
3 |
4 | export {};
5 |
--------------------------------------------------------------------------------
/src/app/readme.md:
--------------------------------------------------------------------------------
1 | # The game app
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './models/room/room';
2 | export * from './models/user/user';
3 | export * from './app/index';
4 |
--------------------------------------------------------------------------------
/src/models/room/readme.md:
--------------------------------------------------------------------------------
1 | # Room
2 |
3 | There's a room class for creating rooms for in-game experience.
4 |
5 | We have to implement these methods inside the room.
6 | ** You can change the method names as properly if you want which that in case.
7 |
8 | ```javascript
9 | const socketId = '1'
10 | const name = 'Cagatay Cali'
11 | const cagatay = new User(socketId, name) // This code will be write at user class
12 |
13 | const socketId = '2'
14 | const name = 'Esma Aydogdu'
15 | const esma = new User(socketId, name) // This code will be write at user class
16 |
17 | Room.allRooms() // this is static method. This method have to return all room names.
18 | Room.getRoom(name) // this is static method. This method have to return given room instance.
19 |
20 | const roomName = 'example room name'
21 | const room = new Room(roomName)
22 |
23 | room.join(cagatay) // nobody in room. room must be return room instance. (tip: return this)
24 | room.join(esma) // cagatay is in the room.
25 |
26 | room.members // must be return instance of users
27 | room.amIHost(cagatay) // returns true
28 | room.amIHost(esma) // returns false
29 |
30 | room.round // must be return 1
31 | room.nextRound(cagatay) // returns true; cagatay have to be allowed to do that (which is creator of room)
32 | room.nextRound(esma) // returns false; cagatay have to be allowed to do that (which is creator of room)
33 |
34 | room.smile(cagatay) // cagatay smiled
35 | room.smile(esma) // esma smiled
36 |
37 | room.getRoundScore() // both smiled, everyone gets 0 point. [esma: 0, cagatay: 0]
38 |
39 | room.nextRound(cagatay) // cagatay started next round
40 | room.smile(esma) // esma smiled, cagatay did not.
41 |
42 | room.getRoundScore() // esma smiled, esma gets 0 point, cagatay get 1. [esma: 0, cagatay: 1]
43 |
44 | room.getOverAllScore() // { 1: [esma: 0, cagatay: 0], 2: [esma: 0, cagatay: 1] }
45 |
46 | room.endGame() // returns winners by sorted overall score // cagatay wins with 1 non-smiled round.
47 |
48 | room.close(cagatay) // returns true; this method delete room instance from all rooms.
49 | room.close(esma) // returns false;
50 | ```
--------------------------------------------------------------------------------
/src/models/room/room.test.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | import { Room } from './room';
3 |
4 | describe('[room.ts]', () => {
5 | it('creates instance of room', () => {
6 | const newRoom = new Room();
7 | expect(newRoom instanceof Room).toBe(true);
8 | });
9 | });
10 |
--------------------------------------------------------------------------------
/src/models/room/room.ts:
--------------------------------------------------------------------------------
1 | export class Room {}
2 |
--------------------------------------------------------------------------------
/src/models/user/readme.md:
--------------------------------------------------------------------------------
1 | # User
2 |
3 | There's a user class for creating user instances for in-game experience.
4 |
5 | We have to implement these methods inside the user.
6 | ** You can change the method names as properly if you want which that in case.
7 |
8 | ```javascript
9 | const socketId = '1'
10 | const name = 'Cagatay Cali'
11 | const cagatay = new User(socketId, name) // This code will be write at user class
12 |
13 | User.all() // this is static method, returns all users as array of instances.
14 | User.get(id) // this is static method, returns given user instance by id.
15 |
16 | const cagatay = new User(socketId, name); // id is socketId, name is username for user.
17 |
18 | cagatay.getRoom() // returns room instance.
19 | cagatay.id // returns socketId
20 | ```
--------------------------------------------------------------------------------
/src/models/user/user.test.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | import { User } from './user';
3 |
4 | describe('[user.ts]', () => {
5 | it('creates instance of user', () => {
6 | const user = new User();
7 | expect(user instanceof User).toBe(true);
8 | });
9 | });
10 |
--------------------------------------------------------------------------------
/src/models/user/user.ts:
--------------------------------------------------------------------------------
1 | export class User {}
2 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 | /* Basic Options */
5 | // "incremental": true, /* Enable incremental compilation */
6 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
7 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
8 | // "lib": [], /* Specify library files to be included in the compilation. */
9 | // "allowJs": true, /* Allow javascript files to be compiled. */
10 | // "checkJs": true, /* Report errors in .js files. */
11 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
12 | "declaration": true, /* Generates corresponding '.d.ts' file. */
13 | "declarationMap": false, /* Generates a sourcemap for each corresponding '.d.ts' file. */
14 | "sourceMap": false, /* Generates corresponding '.map' file. */
15 | // "outFile": "./", /* Concatenate and emit output to single file. */
16 | "outDir": "./dist", /* Redirect output structure to the directory. */
17 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
18 | // "composite": true, /* Enable project compilation */
19 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
20 | // "removeComments": true, /* Do not emit comments to output. */
21 | // "noEmit": true, /* Do not emit outputs. */
22 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */
23 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
24 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
25 | /* Strict Type-Checking Options */
26 | "strict": true, /* Enable all strict type-checking options. */
27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
28 | // "strictNullChecks": true, /* Enable strict null checks. */
29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */
30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
34 | /* Additional Checks */
35 | // "noUnusedLocals": true, /* Report errors on unused locals. */
36 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
37 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
38 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
39 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
40 | /* Module Resolution Options */
41 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
42 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
43 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
44 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
45 | // "typeRoots": [], /* List of folders to include type definitions from. */
46 | // "types": [], /* Type declaration files to be included in compilation. */
47 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
48 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
49 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
50 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
51 | /* Source Map Options */
52 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
53 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
54 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
55 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
56 | /* Experimental Options */
57 | "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
58 | "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
59 | /* Advanced Options */
60 | "skipLibCheck": true, /* Skip type checking of declaration files. */
61 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
62 | },
63 | "exclude": [
64 | "dist",
65 | ],
66 | }
--------------------------------------------------------------------------------