Explorar o código

configure biome for app and include integration tests except service tests for check

Futa Arai hai 8 meses
pai
achega
0376c67d1e

+ 5 - 0
apps/app/.eslintrc.js

@@ -16,6 +16,11 @@ module.exports = {
     'src/linter-checker/**',
     'tmp/**',
     'next-env.d.ts',
+    'test/integration/crowi/**',
+    'test/integration/middlewares/**',
+    'test/integration/migrations/**',
+    'test/integration/models/**',
+    'test/integration/setup.js',
   ],
   settings: {
     // resolve path aliases by eslint-import-resolver-typescript

+ 11 - 4
apps/app/jest.config.js

@@ -22,9 +22,14 @@ module.exports = {
 
       rootDir: '.',
       roots: ['<rootDir>'],
-      testMatch: ['<rootDir>/test/integration/**/*.test.ts', '<rootDir>/test/integration/**/*.test.js'],
+      testMatch: [
+        '<rootDir>/test/integration/**/*.test.ts',
+        '<rootDir>/test/integration/**/*.test.js',
+      ],
       // https://regex101.com/r/jTaxYS/1
-      modulePathIgnorePatterns: ['<rootDir>/test/integration/*.*/v5(..*)*.[t|j]s'],
+      modulePathIgnorePatterns: [
+        '<rootDir>/test/integration/*.*/v5(..*)*.[t|j]s',
+      ],
       testEnvironment: 'node',
       globalSetup: '<rootDir>/test/integration/global-setup.js',
       globalTeardown: '<rootDir>/test/integration/global-teardown.js',
@@ -43,7 +48,10 @@ module.exports = {
 
       rootDir: '.',
       roots: ['<rootDir>'],
-      testMatch: ['<rootDir>/test/integration/**/v5.*.test.ts', '<rootDir>/test/integration/**/v5.*.test.js'],
+      testMatch: [
+        '<rootDir>/test/integration/**/v5.*.test.ts',
+        '<rootDir>/test/integration/**/v5.*.test.js',
+      ],
 
       testEnvironment: 'node',
       globalSetup: '<rootDir>/test/integration/global-setup.js',
@@ -75,5 +83,4 @@ module.exports = {
     '/resource/',
     '/node_modules/',
   ],
-
 };

+ 18 - 15
apps/app/next.config.js

@@ -8,8 +8,10 @@
 const path = require('path');
 
 const { withSuperjson } = require('next-superjson');
-const { PHASE_PRODUCTION_BUILD, PHASE_PRODUCTION_SERVER } = require('next/constants');
-
+const {
+  PHASE_PRODUCTION_BUILD,
+  PHASE_PRODUCTION_SERVER,
+} = require('next/constants');
 
 const getTranspilePackages = () => {
   const { listPrefixedPackages } = require('./src/utils/next.config.utils');
@@ -56,7 +58,14 @@ const getTranspilePackages = () => {
     'github-slugger',
     'html-url-attributes',
     'estree-util-is-identifier-name',
-    ...listPrefixedPackages(['remark-', 'rehype-', 'hast-', 'mdast-', 'micromark-', 'unist-']),
+    ...listPrefixedPackages([
+      'remark-',
+      'rehype-',
+      'hast-',
+      'mdast-',
+      'micromark-',
+      'unist-',
+    ]),
   ];
 
   // const eazyLogger = require('eazy-logger');
@@ -84,13 +93,11 @@ const optimizePackageImports = [
   '@growi/ui',
 ];
 
-module.exports = async(phase, { defaultConfig }) => {
-
+module.exports = async (phase, { defaultConfig }) => {
   const { i18n, localePath } = require('./config/next-i18next.config');
 
   /** @type {import('next').NextConfig} */
   const nextConfig = {
-
     reactStrictMode: true,
     poweredByHeader: false,
     pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js'],
@@ -103,9 +110,8 @@ module.exports = async(phase, { defaultConfig }) => {
     typescript: {
       tsconfigPath: 'tsconfig.build.client.json',
     },
-    transpilePackages: phase !== PHASE_PRODUCTION_SERVER
-      ? getTranspilePackages()
-      : undefined,
+    transpilePackages:
+      phase !== PHASE_PRODUCTION_SERVER ? getTranspilePackages() : undefined,
     experimental: {
       optimizePackageImports,
     },
@@ -150,7 +156,6 @@ module.exports = async(phase, { defaultConfig }) => {
 
       return config;
     },
-
   };
 
   // production server
@@ -159,11 +164,9 @@ module.exports = async(phase, { defaultConfig }) => {
   }
 
   const withBundleAnalyzer = require('@next/bundle-analyzer')({
-    enabled: phase === PHASE_PRODUCTION_BUILD
-      && (
-        process.env.ANALYZE === 'true'
-          || process.env.ANALYZE === '1'
-      ),
+    enabled:
+      phase === PHASE_PRODUCTION_BUILD &&
+      (process.env.ANALYZE === 'true' || process.env.ANALYZE === '1'),
   });
 
   return withBundleAnalyzer(withSuperjson()(nextConfig));

+ 1 - 4
apps/app/nodemon.json

@@ -1,9 +1,6 @@
 {
   "ext": "js,ts,json",
-  "watch": [
-    ".",
-    "../../packages/**/dist"
-  ],
+  "watch": [".", "../../packages/**/dist"],
   "ignore": [
     ".next",
     "public/static",

+ 1 - 0
apps/app/package.json

@@ -28,6 +28,7 @@
     "launch-dev:ci": "cross-env NODE_ENV=development pnpm run dev:migrate && pnpm run ts-node src/server/app.ts --ci",
     "lint:typecheck": "vue-tsc --noEmit",
     "lint:eslint": "eslint --quiet \"**/*.{js,mjs,jsx,ts,mts,tsx}\"",
+    "lint:biome": "biome check",
     "lint:styles": "stylelint \"src/**/*.scss\"",
     "lint:openapi:apiv3": "node node_modules/swagger2openapi/oas-validate tmp/openapi-spec-apiv3.json",
     "lint:openapi:apiv1": "node node_modules/swagger2openapi/oas-validate tmp/openapi-spec-apiv1.json",

+ 14 - 14
apps/app/playwright.config.ts

@@ -10,18 +10,20 @@ const storageState = fs.existsSync(authFile) ? authFile : undefined;
 
 const supportedBrowsers = ['chromium', 'firefox', 'webkit'] as const;
 
-const projects: Array<Project> = supportedBrowsers.map(browser => ({
+const projects: Array<Project> = supportedBrowsers.map((browser) => ({
   name: browser,
   use: { ...devices[`Desktop ${browser}`], storageState },
   testIgnore: /(10-installer|21-basic-features-for-guest)\/.*\.spec\.ts/,
   dependencies: ['setup', 'auth'],
 }));
 
-const projectsForGuestMode: Array<Project> = supportedBrowsers.map(browser => ({
-  name: `${browser}/guest-mode`,
-  use: { ...devices[`Desktop ${browser}`] }, // Do not use storageState
-  testMatch: /21-basic-features-for-guest\/.*\.spec\.ts/,
-}));
+const projectsForGuestMode: Array<Project> = supportedBrowsers.map(
+  (browser) => ({
+    name: `${browser}/guest-mode`,
+    use: { ...devices[`Desktop ${browser}`] }, // Do not use storageState
+    testMatch: /21-basic-features-for-guest\/.*\.spec\.ts/,
+  }),
+);
 
 /**
  * Read environment variables from file.
@@ -48,12 +50,7 @@ export default defineConfig({
   /* Opt out of parallel tests on CI. */
   workers: process.env.CI ? 1 : undefined,
   /* Reporter to use. See https://playwright.dev/docs/test-reporters */
-  reporter: process.env.CI
-    ? [
-      ['github'],
-      ['blob'],
-    ]
-    : 'list',
+  reporter: process.env.CI ? [['github'], ['blob']] : 'list',
 
   webServer: {
     command: 'pnpm run server',
@@ -79,7 +76,11 @@ export default defineConfig({
   /* Configure projects for major browsers */
   projects: [
     // Setup project
-    { name: 'setup', testMatch: /.*\.setup\.ts/, testIgnore: /auth\.setup\.ts/ },
+    {
+      name: 'setup',
+      testMatch: /.*\.setup\.ts/,
+      testIgnore: /auth\.setup\.ts/,
+    },
     { name: 'auth', testMatch: /auth\.setup\.ts/ },
 
     {
@@ -113,5 +114,4 @@ export default defineConfig({
     //   use: { ...devices['Desktop Chrome'], channel: 'chrome' },
     // },
   ],
-
 });

+ 2 - 5
apps/app/test/integration/crowi/crowi.test.js

@@ -3,21 +3,18 @@ import packageJson from '^/package.json';
 const { getInstance } = require('../setup-crowi');
 
 describe('Test for Crowi application context', () => {
-
   describe('construction', () => {
-    test('initialize crowi context', async() => {
+    test('initialize crowi context', async () => {
       const crowi = await getInstance();
       expect(crowi.version).toBe(packageJson.version);
       expect(typeof crowi.env).toBe('object');
     });
 
-    test('config getter, setter', async() => {
+    test('config getter, setter', async () => {
       const crowi = await getInstance();
       expect(crowi.getConfig()).toEqual({});
       crowi.setConfig({ test: 1 });
       expect(crowi.getConfig()).toEqual({ test: 1 });
     });
-
   });
-
 });

+ 43 - 15
apps/app/test/integration/global-setup.js

@@ -4,10 +4,10 @@ import { getMongoUri, mongoOptions } from '~/server/util/mongoose-utils';
 
 // check env
 if (process.env.NODE_ENV !== 'test') {
-  throw new Error('\'process.env.NODE_ENV\' must be \'test\'');
+  throw new Error("'process.env.NODE_ENV' must be 'test'");
 }
 
-module.exports = async() => {
+module.exports = async () => {
   await mongoose.connect(getMongoUri(), mongoOptions);
 
   // drop database
@@ -17,25 +17,51 @@ module.exports = async() => {
   const pageCollection = mongoose.connection.collection('pages');
   const userCollection = mongoose.connection.collection('users');
   const userGroupCollection = mongoose.connection.collection('usergroups');
-  const userGroupRelationsCollection = mongoose.connection.collection('usergrouprelations');
+  const userGroupRelationsCollection =
+    mongoose.connection.collection('usergrouprelations');
 
   // create global user & rootPage
-  const globalUser = (await userCollection.insertMany([{ name: 'globalUser', username: 'globalUser', email: 'globalUser@example.com' }]))[0];
+  const globalUser = (
+    await userCollection.insertMany([
+      {
+        name: 'globalUser',
+        username: 'globalUser',
+        email: 'globalUser@example.com',
+      },
+    ])
+  )[0];
   const gGroupUserId1 = new mongoose.Types.ObjectId();
   const gGroupUserId2 = new mongoose.Types.ObjectId();
   const gGroupUserId3 = new mongoose.Types.ObjectId();
 
   await userCollection.insertMany([
-    { name: 'v5DummyUser1', username: 'v5DummyUser1', email: 'v5DummyUser1@example.com' },
-    { name: 'v5DummyUser2', username: 'v5DummyUser2', email: 'v5DummyUser2@example.com' },
     {
-      _id: gGroupUserId1, name: 'gGroupUser1', username: 'gGroupUser1', email: 'gGroupUser1@example.com',
+      name: 'v5DummyUser1',
+      username: 'v5DummyUser1',
+      email: 'v5DummyUser1@example.com',
     },
     {
-      _id: gGroupUserId2, name: 'gGroupUser2', username: 'gGroupUser2', email: 'gGroupUser2@example.com',
+      name: 'v5DummyUser2',
+      username: 'v5DummyUser2',
+      email: 'v5DummyUser2@example.com',
     },
     {
-      _id: gGroupUserId3, name: 'gGroupUser3', username: 'gGroupUser3', email: 'gGroupUser3@example.com',
+      _id: gGroupUserId1,
+      name: 'gGroupUser1',
+      username: 'gGroupUser1',
+      email: 'gGroupUser1@example.com',
+    },
+    {
+      _id: gGroupUserId2,
+      name: 'gGroupUser2',
+      username: 'gGroupUser2',
+      email: 'gGroupUser2@example.com',
+    },
+    {
+      _id: gGroupUserId3,
+      name: 'gGroupUser3',
+      username: 'gGroupUser3',
+      email: 'gGroupUser3@example.com',
     },
   ]);
   const gGroupIdIsolate = new mongoose.Types.ObjectId();
@@ -104,12 +130,14 @@ module.exports = async() => {
       createdAt: new Date(),
     },
   ]);
-  await pageCollection.insertMany([{
-    path: '/',
-    grant: 1,
-    creator: globalUser,
-    lastUpdateUser: globalUser,
-  }]);
+  await pageCollection.insertMany([
+    {
+      path: '/',
+      grant: 1,
+      creator: globalUser,
+      lastUpdateUser: globalUser,
+    },
+  ]);
 
   await mongoose.disconnect();
 };

+ 1 - 2
apps/app/test/integration/global-teardown.js

@@ -5,5 +5,4 @@
  * are NOT available in setup scripts
  *********************************************************** */
 
-module.exports = async() => {
-};
+module.exports = async () => {};

+ 101 - 89
apps/app/test/integration/middlewares/login-required.test.js

@@ -10,11 +10,17 @@ describe('loginRequired', () => {
   let loginRequired;
   let loginRequiredWithFallback;
 
-  beforeEach(async() => {
+  beforeEach(async () => {
     crowi = await getInstance();
-    loginRequiredStrictly = require('~/server/middlewares/login-required')(crowi);
+    loginRequiredStrictly = require('~/server/middlewares/login-required')(
+      crowi,
+    );
     loginRequired = require('~/server/middlewares/login-required')(crowi, true);
-    loginRequiredWithFallback = require('~/server/middlewares/login-required')(crowi, false, fallbackMock);
+    loginRequiredWithFallback = require('~/server/middlewares/login-required')(
+      crowi,
+      false,
+      fallbackMock,
+    );
   });
 
   describe('not strict mode', () => {
@@ -29,7 +35,7 @@ describe('loginRequired', () => {
 
       let isGuestAllowedToReadSpy;
 
-      beforeEach(async() => {
+      beforeEach(async () => {
         // setup req
         req = {
           originalUrl: 'original url 1',
@@ -38,37 +44,40 @@ describe('loginRequired', () => {
         // reset session object
         req.session = {};
         // prepare spy for AclService.isGuestAllowedToRead
-        isGuestAllowedToReadSpy = jest.spyOn(crowi.aclService, 'isGuestAllowedToRead')
+        isGuestAllowedToReadSpy = jest
+          .spyOn(crowi.aclService, 'isGuestAllowedToRead')
           .mockImplementation(() => false);
       });
 
       /* eslint-disable indent */
       test.each`
-        userStatus  | expectedPath
-        ${1}        | ${'/login/error/registered'}
-        ${3}        | ${'/login/error/suspended'}
-        ${5}        | ${'/invited'}
-      `('redirect to \'$expectedPath\' when user.status is \'$userStatus\'', ({ userStatus, expectedPath }) => {
-
-        req.user = {
-          _id: 'user id',
-          status: userStatus,
-        };
-
-        const result = loginRequired(req, res, next);
-
-        expect(isGuestAllowedToReadSpy).not.toHaveBeenCalled();
-        expect(next).not.toHaveBeenCalled();
-        expect(fallbackMock).not.toHaveBeenCalled();
-        expect(res.sendStatus).not.toHaveBeenCalled();
-        expect(res.redirect).toHaveBeenCalledTimes(1);
-        expect(res.redirect).toHaveBeenCalledWith(expectedPath);
-        expect(result).toBe('redirect');
-        expect(req.session.redirectTo).toBe(undefined);
-      });
+        userStatus | expectedPath
+        ${1}       | ${'/login/error/registered'}
+        ${3}       | ${'/login/error/suspended'}
+        ${5}       | ${'/invited'}
+      `(
+        "redirect to '$expectedPath' when user.status is '$userStatus'",
+        ({ userStatus, expectedPath }) => {
+          req.user = {
+            _id: 'user id',
+            status: userStatus,
+          };
+
+          const result = loginRequired(req, res, next);
+
+          expect(isGuestAllowedToReadSpy).not.toHaveBeenCalled();
+          expect(next).not.toHaveBeenCalled();
+          expect(fallbackMock).not.toHaveBeenCalled();
+          expect(res.sendStatus).not.toHaveBeenCalled();
+          expect(res.redirect).toHaveBeenCalledTimes(1);
+          expect(res.redirect).toHaveBeenCalledWith(expectedPath);
+          expect(result).toBe('redirect');
+          expect(req.session.redirectTo).toBe(undefined);
+        },
+      );
       /* eslint-disable indent */
 
-      test('redirect to \'/login\' when the user does not loggedin', () => {
+      test("redirect to '/login' when the user does not loggedin", () => {
         req.baseUrl = '/path/that/requires/loggedin';
 
         const result = loginRequired(req, res, next);
@@ -84,7 +93,6 @@ describe('loginRequired', () => {
       });
 
       test('pass anyone into sharedPage', () => {
-
         req.isSharedPage = true;
 
         const result = loginRequired(req, res, next);
@@ -96,7 +104,6 @@ describe('loginRequired', () => {
         expect(res.redirect).not.toHaveBeenCalled();
         expect(result).toBe('next');
       });
-
     });
 
     describe('and when aclService.isGuestAllowedToRead() returns true', () => {
@@ -104,7 +111,7 @@ describe('loginRequired', () => {
 
       let isGuestAllowedToReadSpy;
 
-      beforeEach(async() => {
+      beforeEach(async () => {
         // setup req
         req = {
           originalUrl: 'original url 1',
@@ -113,38 +120,40 @@ describe('loginRequired', () => {
         // reset session object
         req.session = {};
         // prepare spy for AclService.isGuestAllowedToRead
-        isGuestAllowedToReadSpy = jest.spyOn(crowi.aclService, 'isGuestAllowedToRead')
+        isGuestAllowedToReadSpy = jest
+          .spyOn(crowi.aclService, 'isGuestAllowedToRead')
           .mockImplementation(() => true);
       });
 
       /* eslint-disable indent */
       test.each`
-        userStatus  | expectedPath
-        ${1}        | ${'/login/error/registered'}
-        ${3}        | ${'/login/error/suspended'}
-        ${5}        | ${'/invited'}
-      `('redirect to \'$expectedPath\' when user.status is \'$userStatus\'', ({ userStatus, expectedPath }) => {
-
-        req.user = {
-          _id: 'user id',
-          status: userStatus,
-        };
-
-        const result = loginRequired(req, res, next);
-
-        expect(isGuestAllowedToReadSpy).not.toHaveBeenCalled();
-        expect(next).not.toHaveBeenCalled();
-        expect(fallbackMock).not.toHaveBeenCalled();
-        expect(res.sendStatus).not.toHaveBeenCalled();
-        expect(res.redirect).toHaveBeenCalledTimes(1);
-        expect(res.redirect).toHaveBeenCalledWith(expectedPath);
-        expect(result).toBe('redirect');
-        expect(req.session.redirectTo).toBe(undefined);
-      });
+        userStatus | expectedPath
+        ${1}       | ${'/login/error/registered'}
+        ${3}       | ${'/login/error/suspended'}
+        ${5}       | ${'/invited'}
+      `(
+        "redirect to '$expectedPath' when user.status is '$userStatus'",
+        ({ userStatus, expectedPath }) => {
+          req.user = {
+            _id: 'user id',
+            status: userStatus,
+          };
+
+          const result = loginRequired(req, res, next);
+
+          expect(isGuestAllowedToReadSpy).not.toHaveBeenCalled();
+          expect(next).not.toHaveBeenCalled();
+          expect(fallbackMock).not.toHaveBeenCalled();
+          expect(res.sendStatus).not.toHaveBeenCalled();
+          expect(res.redirect).toHaveBeenCalledTimes(1);
+          expect(res.redirect).toHaveBeenCalledWith(expectedPath);
+          expect(result).toBe('redirect');
+          expect(req.session.redirectTo).toBe(undefined);
+        },
+      );
       /* eslint-disable indent */
 
       test('pass guest user', () => {
-
         const result = loginRequired(req, res, next);
 
         expect(isGuestAllowedToReadSpy).toHaveBeenCalledTimes(1);
@@ -156,7 +165,6 @@ describe('loginRequired', () => {
       });
 
       test('pass anyone into sharedPage', () => {
-
         req.isSharedPage = true;
 
         const result = loginRequired(req, res, next);
@@ -168,12 +176,9 @@ describe('loginRequired', () => {
         expect(res.redirect).not.toHaveBeenCalled();
         expect(result).toBe('next');
       });
-
     });
-
   });
 
-
   describe('strict mode', () => {
     // setup req/res/next
     const req = {
@@ -188,14 +193,17 @@ describe('loginRequired', () => {
 
     let isGuestAllowedToReadSpy;
 
-    beforeEach(async() => {
+    beforeEach(async () => {
       // reset session object
       req.session = {};
       // spy for AclService.isGuestAllowedToRead
-      isGuestAllowedToReadSpy = jest.spyOn(crowi.aclService, 'isGuestAllowedToRead');
+      isGuestAllowedToReadSpy = jest.spyOn(
+        crowi.aclService,
+        'isGuestAllowedToRead',
+      );
     });
 
-    test('send status 403 when \'req.baseUrl\' starts with \'_api\'', () => {
+    test("send status 403 when 'req.baseUrl' starts with '_api'", () => {
       req.baseUrl = '/_api/someapi';
 
       const result = loginRequiredStrictly(req, res, next);
@@ -209,7 +217,7 @@ describe('loginRequired', () => {
       expect(result).toBe('sendStatus');
     });
 
-    test('redirect to \'/login\' when the user does not loggedin', () => {
+    test("redirect to '/login' when the user does not loggedin", () => {
       req.baseUrl = '/path/that/requires/loggedin';
 
       const result = loginRequiredStrictly(req, res, next);
@@ -245,30 +253,33 @@ describe('loginRequired', () => {
 
     /* eslint-disable indent */
     test.each`
-      userStatus  | expectedPath
-      ${1}        | ${'/login/error/registered'}
-      ${3}        | ${'/login/error/suspended'}
-      ${5}        | ${'/invited'}
-    `('redirect to \'$expectedPath\' when user.status is \'$userStatus\'', ({ userStatus, expectedPath }) => {
-      req.user = {
-        _id: 'user id',
-        status: userStatus,
-      };
+      userStatus | expectedPath
+      ${1}       | ${'/login/error/registered'}
+      ${3}       | ${'/login/error/suspended'}
+      ${5}       | ${'/invited'}
+    `(
+      "redirect to '$expectedPath' when user.status is '$userStatus'",
+      ({ userStatus, expectedPath }) => {
+        req.user = {
+          _id: 'user id',
+          status: userStatus,
+        };
 
-      const result = loginRequiredStrictly(req, res, next);
+        const result = loginRequiredStrictly(req, res, next);
 
-      expect(isGuestAllowedToReadSpy).not.toHaveBeenCalled();
-      expect(next).not.toHaveBeenCalled();
-      expect(fallbackMock).not.toHaveBeenCalled();
-      expect(res.sendStatus).not.toHaveBeenCalled();
-      expect(res.redirect).toHaveBeenCalledTimes(1);
-      expect(res.redirect).toHaveBeenCalledWith(expectedPath);
-      expect(result).toBe('redirect');
-      expect(req.session.redirectTo).toBe(undefined);
-    });
+        expect(isGuestAllowedToReadSpy).not.toHaveBeenCalled();
+        expect(next).not.toHaveBeenCalled();
+        expect(fallbackMock).not.toHaveBeenCalled();
+        expect(res.sendStatus).not.toHaveBeenCalled();
+        expect(res.redirect).toHaveBeenCalledTimes(1);
+        expect(res.redirect).toHaveBeenCalledWith(expectedPath);
+        expect(result).toBe('redirect');
+        expect(req.session.redirectTo).toBe(undefined);
+      },
+    );
     /* eslint-disable indent */
 
-    test('redirect to \'/login\' when user.status is \'STATUS_DELETED\'', () => {
+    test("redirect to '/login' when user.status is 'STATUS_DELETED'", () => {
       const User = crowi.model('User');
 
       req.baseUrl = '/path/that/requires/loggedin';
@@ -288,7 +299,6 @@ describe('loginRequired', () => {
       expect(result).toBe('redirect');
       expect(req.session.redirectTo).toBe(undefined);
     });
-
   });
 
   describe('specified fallback', () => {
@@ -305,14 +315,17 @@ describe('loginRequired', () => {
 
     let isGuestAllowedToReadSpy;
 
-    beforeEach(async() => {
+    beforeEach(async () => {
       // reset session object
       req.session = {};
       // spy for AclService.isGuestAllowedToRead
-      isGuestAllowedToReadSpy = jest.spyOn(crowi.aclService, 'isGuestAllowedToRead');
-          });
+      isGuestAllowedToReadSpy = jest.spyOn(
+        crowi.aclService,
+        'isGuestAllowedToRead',
+      );
+    });
 
-    test('invoke fallback when \'req.path\' starts with \'_api\'', () => {
+    test("invoke fallback when 'req.path' starts with '_api'", () => {
       req.path = '/_api/someapi';
 
       const result = loginRequiredWithFallback(req, res, next);
@@ -339,6 +352,5 @@ describe('loginRequired', () => {
       expect(fallbackMock).toHaveBeenCalledWith(req, res, next);
       expect(result).toBe('fallback');
     });
-
   });
 });

+ 15 - 14
apps/app/test/integration/migrations/20210913153942-migrate-slack-app-integration-schema.test.ts

@@ -1,29 +1,35 @@
-import { Collection } from 'mongodb';
+import type { Collection } from 'mongodb';
 import mongoose from 'mongoose';
 
 import migrate from '~/migrations/20210913153942-migrate-slack-app-integration-schema';
 
 describe('migrate-slack-app-integration-schema', () => {
-
   let collection: Collection;
 
-  beforeAll(async() => {
+  beforeAll(async () => {
     collection = mongoose.connection.collection('slackappintegrations');
 
     await collection.insertMany([
       {
-        tokenGtoP: 'tokenGtoP1', tokenPtoG: 'tokenPtoG1', permissionsForBroadcastUseCommands: { foo: true }, permissionsForSingleUseCommands: { bar: true },
+        tokenGtoP: 'tokenGtoP1',
+        tokenPtoG: 'tokenPtoG1',
+        permissionsForBroadcastUseCommands: { foo: true },
+        permissionsForSingleUseCommands: { bar: true },
       },
       {
-        tokenGtoP: 'tokenGtoP2', tokenPtoG: 'tokenPtoG2', supportedCommandsForBroadcastUse: ['foo'], supportedCommandsForSingleUse: ['bar'],
+        tokenGtoP: 'tokenGtoP2',
+        tokenPtoG: 'tokenPtoG2',
+        supportedCommandsForBroadcastUse: ['foo'],
+        supportedCommandsForSingleUse: ['bar'],
       },
       {
-        tokenGtoP: 'tokenGtoP3', tokenPtoG: 'tokenPtoG3',
+        tokenGtoP: 'tokenGtoP3',
+        tokenPtoG: 'tokenPtoG3',
       },
     ]);
   });
 
-  test('up is applied successfully', async() => {
+  test('up is applied successfully', async () => {
     // setup
     const doc1 = await collection.findOne({ tokenGtoP: 'tokenGtoP1' });
     const doc2 = await collection.findOne({ tokenGtoP: 'tokenGtoP2' });
@@ -46,12 +52,8 @@ describe('migrate-slack-app-integration-schema', () => {
       _id: doc2?._id,
       tokenGtoP: 'tokenGtoP2',
       tokenPtoG: 'tokenPtoG2',
-      supportedCommandsForBroadcastUse: [
-        'foo',
-      ],
-      supportedCommandsForSingleUse: [
-        'bar',
-      ],
+      supportedCommandsForBroadcastUse: ['foo'],
+      supportedCommandsForSingleUse: ['bar'],
     });
     expect(doc3).toStrictEqual({
       _id: doc3?._id,
@@ -116,5 +118,4 @@ describe('migrate-slack-app-integration-schema', () => {
       },
     });
   });
-
 });

+ 40 - 22
apps/app/test/integration/models/page-redirect.test.js

@@ -7,19 +7,19 @@ describe('PageRedirect', () => {
   let crowi;
   let PageRedirect;
 
-  beforeAll(async() => {
+  beforeAll(async () => {
     crowi = await getInstance();
 
     PageRedirect = mongoose.model('PageRedirect');
   });
 
-  beforeEach(async() => {
+  beforeEach(async () => {
     // clear collection
     await PageRedirect.deleteMany({});
   });
 
   describe('.removePageRedirectsByToPath', () => {
-    test('works fine', async() => {
+    test('works fine', async () => {
       // setup:
       await PageRedirect.insertMany([
         { fromPath: '/org/path1', toPath: '/path1' },
@@ -28,48 +28,66 @@ describe('PageRedirect', () => {
         { fromPath: '/org/path33', toPath: '/org/path333' },
         { fromPath: '/org/path333', toPath: '/path3' },
       ]);
-      expect(await PageRedirect.findOne({ fromPath: '/org/path1' })).not.toBeNull();
-      expect(await PageRedirect.findOne({ fromPath: '/org/path2' })).not.toBeNull();
-      expect(await PageRedirect.findOne({ fromPath: '/org/path3' })).not.toBeNull();
-      expect(await PageRedirect.findOne({ fromPath: '/org/path33' })).not.toBeNull();
-      expect(await PageRedirect.findOne({ fromPath: '/org/path333' })).not.toBeNull();
+      expect(
+        await PageRedirect.findOne({ fromPath: '/org/path1' }),
+      ).not.toBeNull();
+      expect(
+        await PageRedirect.findOne({ fromPath: '/org/path2' }),
+      ).not.toBeNull();
+      expect(
+        await PageRedirect.findOne({ fromPath: '/org/path3' }),
+      ).not.toBeNull();
+      expect(
+        await PageRedirect.findOne({ fromPath: '/org/path33' }),
+      ).not.toBeNull();
+      expect(
+        await PageRedirect.findOne({ fromPath: '/org/path333' }),
+      ).not.toBeNull();
 
       // when:
       // remove all documents that have { toPath: '/path/3' }
       await PageRedirect.removePageRedirectsByToPath('/path3');
 
       // then:
-      expect(await PageRedirect.findOne({ fromPath: '/org/path1' })).not.toBeNull();
-      expect(await PageRedirect.findOne({ fromPath: '/org/path2' })).not.toBeNull();
+      expect(
+        await PageRedirect.findOne({ fromPath: '/org/path1' }),
+      ).not.toBeNull();
+      expect(
+        await PageRedirect.findOne({ fromPath: '/org/path2' }),
+      ).not.toBeNull();
       expect(await PageRedirect.findOne({ fromPath: '/org/path3' })).toBeNull();
-      expect(await PageRedirect.findOne({ fromPath: '/org/path33' })).toBeNull();
-      expect(await PageRedirect.findOne({ fromPath: '/org/path333' })).toBeNull();
+      expect(
+        await PageRedirect.findOne({ fromPath: '/org/path33' }),
+      ).toBeNull();
+      expect(
+        await PageRedirect.findOne({ fromPath: '/org/path333' }),
+      ).toBeNull();
     });
   });
 
   describe('.retrievePageRedirectEndpoints', () => {
-    test('shoud return null when data is not found', async() => {
+    test('shoud return null when data is not found', async () => {
       // setup:
       expect(await PageRedirect.findOne({ fromPath: '/path1' })).toBeNull();
 
       // when:
       // retrieve
-      const endpoints = await PageRedirect.retrievePageRedirectEndpoints('/path1');
+      const endpoints =
+        await PageRedirect.retrievePageRedirectEndpoints('/path1');
 
       // then:
       expect(endpoints).toBeNull();
     });
 
-    test('shoud return IPageRedirectEnds (start and end is the same)', async() => {
+    test('shoud return IPageRedirectEnds (start and end is the same)', async () => {
       // setup:
-      await PageRedirect.insertMany([
-        { fromPath: '/path1', toPath: '/path2' },
-      ]);
+      await PageRedirect.insertMany([{ fromPath: '/path1', toPath: '/path2' }]);
       expect(await PageRedirect.findOne({ fromPath: '/path1' })).not.toBeNull();
 
       // when:
       // retrieve
-      const endpoints = await PageRedirect.retrievePageRedirectEndpoints('/path1');
+      const endpoints =
+        await PageRedirect.retrievePageRedirectEndpoints('/path1');
 
       // then:
       expect(endpoints).not.toBeNull();
@@ -81,7 +99,7 @@ describe('PageRedirect', () => {
       expect(endpoints.end.toPath).toEqual('/path2');
     });
 
-    test('shoud return IPageRedirectEnds', async() => {
+    test('shoud return IPageRedirectEnds', async () => {
       // setup:
       await PageRedirect.insertMany([
         { fromPath: '/path1', toPath: '/path2' },
@@ -94,7 +112,8 @@ describe('PageRedirect', () => {
 
       // when:
       // retrieve
-      const endpoints = await PageRedirect.retrievePageRedirectEndpoints('/path1');
+      const endpoints =
+        await PageRedirect.retrievePageRedirectEndpoints('/path1');
 
       // then:
       expect(endpoints).not.toBeNull();
@@ -106,5 +125,4 @@ describe('PageRedirect', () => {
       expect(endpoints.end.toPath).toEqual('/path4');
     });
   });
-
 });

+ 98 - 50
apps/app/test/integration/models/page.test.js

@@ -17,7 +17,7 @@ describe('Page', () => {
   let UserGroup;
   let UserGroupRelation;
 
-  beforeAll(async() => {
+  beforeAll(async () => {
     crowi = await getInstance();
 
     User = mongoose.model('User');
@@ -26,11 +26,22 @@ describe('Page', () => {
     Page = mongoose.model('Page');
     PageQueryBuilder = Page.PageQueryBuilder;
 
-
     await User.insertMany([
-      { name: 'Anon 0', username: 'anonymous0', email: 'anonymous0@example.com' },
-      { name: 'Anon 1', username: 'anonymous1', email: 'anonymous1@example.com' },
-      { name: 'Anon 2', username: 'anonymous2', email: 'anonymous2@example.com' },
+      {
+        name: 'Anon 0',
+        username: 'anonymous0',
+        email: 'anonymous0@example.com',
+      },
+      {
+        name: 'Anon 1',
+        username: 'anonymous1',
+        email: 'anonymous1@example.com',
+      },
+      {
+        name: 'Anon 2',
+        username: 'anonymous2',
+        email: 'anonymous2@example.com',
+      },
     ]);
 
     await UserGroup.insertMany([
@@ -126,7 +137,7 @@ describe('Page', () => {
 
   describe('.isPublic', () => {
     describe('with a public page', () => {
-      test('should return true', async() => {
+      test('should return true', async () => {
         const page = await Page.findOne({ path: '/grant/public' });
         expect(page.isPublic()).toEqual(true);
       });
@@ -134,7 +145,7 @@ describe('Page', () => {
 
     ['restricted', 'specified', 'owner'].forEach((grant) => {
       describe(`with a ${grant} page`, () => {
-        test('should return false', async() => {
+        test('should return false', async () => {
           const page = await Page.findOne({ path: `/grant/${grant}` });
           expect(page.isPublic()).toEqual(false);
         });
@@ -152,20 +163,22 @@ describe('Page', () => {
     test('should return reverted trash page name', () => {
       expect(Page.getRevertDeletedPageName('/hoge')).toEqual('/hoge');
       expect(Page.getRevertDeletedPageName('/trash/hoge')).toEqual('/hoge');
-      expect(Page.getRevertDeletedPageName('/trash/hoge/trash')).toEqual('/hoge/trash');
+      expect(Page.getRevertDeletedPageName('/trash/hoge/trash')).toEqual(
+        '/hoge/trash',
+      );
     });
   });
 
   describe('.isAccessiblePageByViewer', () => {
     describe('with a granted page', () => {
-      test('should return true with granted user', async() => {
+      test('should return true with granted user', async () => {
         const user = await User.findOne({ email: 'anonymous0@example.com' });
         const page = await Page.findOne({ path: '/user/anonymous0/memo' });
 
         const bool = await Page.isAccessiblePageByViewer(page.id, user);
         expect(bool).toEqual(true);
       });
-      test('should return false without user', async() => {
+      test('should return false without user', async () => {
         const user = null;
         const page = await Page.findOne({ path: '/user/anonymous0/memo' });
 
@@ -175,14 +188,14 @@ describe('Page', () => {
     });
 
     describe('with a public page', () => {
-      test('should return true with user', async() => {
+      test('should return true with user', async () => {
         const user = await User.findOne({ email: 'anonymous1@example.com' });
         const page = await Page.findOne({ path: '/grant/public' });
 
         const bool = await Page.isAccessiblePageByViewer(page.id, user);
         expect(bool).toEqual(true);
       });
-      test('should return true with out', async() => {
+      test('should return true with out', async () => {
         const user = null;
         const page = await Page.findOne({ path: '/grant/public' });
 
@@ -192,14 +205,14 @@ describe('Page', () => {
     });
 
     describe('with a restricted page', () => {
-      test('should return false with user who has no grant', async() => {
+      test('should return false with user who has no grant', async () => {
         const user = await User.findOne({ email: 'anonymous1@example.com' });
         const page = await Page.findOne({ path: '/grant/owner' });
 
         const bool = await Page.isAccessiblePageByViewer(page.id, user);
         expect(bool).toEqual(false);
       });
-      test('should return false without user', async() => {
+      test('should return false without user', async () => {
         const user = null;
         const page = await Page.findOne({ path: '/grant/owner' });
 
@@ -211,28 +224,28 @@ describe('Page', () => {
 
   describe('.findPage', () => {
     describe('findByIdAndViewer', () => {
-      test('should find page (public)', async() => {
+      test('should find page (public)', async () => {
         const expectedPage = await Page.findOne({ path: '/grant/public' });
         const page = await Page.findByIdAndViewer(expectedPage.id, testUser0);
         expect(page).not.toBeNull();
         expect(page.path).toEqual(expectedPage.path);
       });
 
-      test('should find page (anyone knows link)', async() => {
+      test('should find page (anyone knows link)', async () => {
         const expectedPage = await Page.findOne({ path: '/grant/restricted' });
         const page = await Page.findByIdAndViewer(expectedPage.id, testUser1);
         expect(page).not.toBeNull();
         expect(page.path).toEqual(expectedPage.path);
       });
 
-      test('should find page (only me)', async() => {
+      test('should find page (only me)', async () => {
         const expectedPage = await Page.findOne({ path: '/grant/owner' });
         const page = await Page.findByIdAndViewer(expectedPage.id, testUser0);
         expect(page).not.toBeNull();
         expect(page.path).toEqual(expectedPage.path);
       });
 
-      test('should not be found by grant (only me)', async() => {
+      test('should not be found by grant (only me)', async () => {
         const expectedPage = await Page.findOne({ path: '/grant/owner' });
         const page = await Page.findByIdAndViewer(expectedPage.id, testUser1);
         expect(page).toBeNull();
@@ -240,14 +253,14 @@ describe('Page', () => {
     });
 
     describe('findByIdAndViewer granted userGroup', () => {
-      test('should find page', async() => {
+      test('should find page', async () => {
         const expectedPage = await Page.findOne({ path: '/grant/groupacl' });
         const page = await Page.findByIdAndViewer(expectedPage.id, testUser0);
         expect(page).not.toBeNull();
         expect(page.path).toEqual(expectedPage.path);
       });
 
-      test('should not be found by grant', async() => {
+      test('should not be found by grant', async () => {
         const expectedPage = await Page.findOne({ path: '/grant/groupacl' });
         const page = await Page.findByIdAndViewer(expectedPage.id, testUser2);
         expect(page).toBeNull();
@@ -256,7 +269,7 @@ describe('Page', () => {
   });
 
   describe('PageQueryBuilder.addConditionToListWithDescendants', () => {
-    test('can retrieve descendants of /page', async() => {
+    test('can retrieve descendants of /page', async () => {
       const builder = new PageQueryBuilder(Page.find());
       builder.addConditionToListWithDescendants('/page');
 
@@ -265,11 +278,13 @@ describe('Page', () => {
       // assert totalCount
       expect(result.length).toEqual(1);
       // assert paths
-      const pagePaths = result.map((page) => { return page.path });
+      const pagePaths = result.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/page/child/without/parents');
     });
 
-    test('can retrieve descendants of /page1', async() => {
+    test('can retrieve descendants of /page1', async () => {
       const builder = new PageQueryBuilder(Page.find());
       builder.addConditionToListWithDescendants('/page1/');
 
@@ -278,14 +293,16 @@ describe('Page', () => {
       // assert totalCount
       expect(result.length).toEqual(2);
       // assert paths
-      const pagePaths = result.map((page) => { return page.path });
+      const pagePaths = result.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/page1');
       expect(pagePaths).toContainEqual('/page1/child1');
     });
   });
 
   describe('PageQueryBuilder.addConditionToListOnlyDescendants', () => {
-    test('can retrieve only descendants of /page', async() => {
+    test('can retrieve only descendants of /page', async () => {
       const builder = new PageQueryBuilder(Page.find());
       builder.addConditionToListOnlyDescendants('/page');
 
@@ -294,11 +311,13 @@ describe('Page', () => {
       // assert totalCount
       expect(result.length).toEqual(1);
       // assert paths
-      const pagePaths = result.map((page) => { return page.path });
+      const pagePaths = result.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/page/child/without/parents');
     });
 
-    test('can retrieve only descendants of /page1', async() => {
+    test('can retrieve only descendants of /page1', async () => {
       const builder = new PageQueryBuilder(Page.find());
       builder.addConditionToListOnlyDescendants('/page1');
 
@@ -307,13 +326,15 @@ describe('Page', () => {
       // assert totalCount
       expect(result.length).toEqual(1);
       // assert paths
-      const pagePaths = result.map((page) => { return page.path });
+      const pagePaths = result.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/page1/child1');
     });
   });
 
   describe('PageQueryBuilder.addConditionToListByStartWith', () => {
-    test('can retrieve pages which starts with /page', async() => {
+    test('can retrieve pages which starts with /page', async () => {
       const builder = new PageQueryBuilder(Page.find());
       builder.addConditionToListByStartWith('/page');
 
@@ -322,7 +343,9 @@ describe('Page', () => {
       // assert totalCount
       expect(result.length).toEqual(4);
       // assert paths
-      const pagePaths = result.map((page) => { return page.path });
+      const pagePaths = result.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/page/child/without/parents');
       expect(pagePaths).toContainEqual('/page1');
       expect(pagePaths).toContainEqual('/page1/child1');
@@ -331,7 +354,7 @@ describe('Page', () => {
   });
 
   describe('.findListWithDescendants', () => {
-    test('can retrieve all pages with testUser0', async() => {
+    test('can retrieve all pages with testUser0', async () => {
       const result = await Page.findListWithDescendants('/grant', testUser0);
       const { pages } = result;
 
@@ -339,7 +362,9 @@ describe('Page', () => {
       expect(pages.length).toEqual(5);
 
       // assert paths
-      const pagePaths = await pages.map((page) => { return page.path });
+      const pagePaths = await pages.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/grant/groupacl');
       expect(pagePaths).toContainEqual('/grant/specified');
       expect(pagePaths).toContainEqual('/grant/owner');
@@ -347,7 +372,7 @@ describe('Page', () => {
       expect(pagePaths).toContainEqual('/grant');
     });
 
-    test('can retrieve all pages with testUser1', async() => {
+    test('can retrieve all pages with testUser1', async () => {
       const result = await Page.findListWithDescendants('/grant', testUser1);
       const { pages } = result;
 
@@ -355,7 +380,9 @@ describe('Page', () => {
       expect(pages.length).toEqual(5);
 
       // assert paths
-      const pagePaths = await pages.map((page) => { return page.path });
+      const pagePaths = await pages.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/grant/groupacl');
       expect(pagePaths).toContainEqual('/grant/specified');
       expect(pagePaths).toContainEqual('/grant/owner');
@@ -363,7 +390,7 @@ describe('Page', () => {
       expect(pagePaths).toContainEqual('/grant');
     });
 
-    test('can retrieve all pages with testUser2', async() => {
+    test('can retrieve all pages with testUser2', async () => {
       const result = await Page.findListWithDescendants('/grant', testUser2);
       const { pages } = result;
 
@@ -371,7 +398,9 @@ describe('Page', () => {
       expect(pages.length).toEqual(5);
 
       // assert paths
-      const pagePaths = await pages.map((page) => { return page.path });
+      const pagePaths = await pages.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/grant/groupacl');
       expect(pagePaths).toContainEqual('/grant/specified');
       expect(pagePaths).toContainEqual('/grant/owner');
@@ -379,7 +408,7 @@ describe('Page', () => {
       expect(pagePaths).toContainEqual('/grant');
     });
 
-    test('can retrieve all pages without user', async() => {
+    test('can retrieve all pages without user', async () => {
       const result = await Page.findListWithDescendants('/grant', null);
       const { pages } = result;
 
@@ -387,7 +416,9 @@ describe('Page', () => {
       expect(pages.length).toEqual(5);
 
       // assert paths
-      const pagePaths = await pages.map((page) => { return page.path });
+      const pagePaths = await pages.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/grant/groupacl');
       expect(pagePaths).toContainEqual('/grant/specified');
       expect(pagePaths).toContainEqual('/grant/owner');
@@ -397,14 +428,19 @@ describe('Page', () => {
   });
 
   describe('.findManageableListWithDescendants', () => {
-    test('can retrieve all pages with testUser0', async() => {
-      const pages = await Page.findManageableListWithDescendants(parentPage, testUser0);
+    test('can retrieve all pages with testUser0', async () => {
+      const pages = await Page.findManageableListWithDescendants(
+        parentPage,
+        testUser0,
+      );
 
       // assert totalCount
       expect(pages.length).toEqual(5);
 
       // assert paths
-      const pagePaths = await pages.map((page) => { return page.path });
+      const pagePaths = await pages.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/grant/groupacl');
       expect(pagePaths).toContainEqual('/grant/specified');
       expect(pagePaths).toContainEqual('/grant/owner');
@@ -412,37 +448,49 @@ describe('Page', () => {
       expect(pagePaths).toContainEqual('/grant');
     });
 
-    test('can retrieve group page and public page which starts with testUser1', async() => {
-      const pages = await Page.findManageableListWithDescendants(parentPage, testUser1);
+    test('can retrieve group page and public page which starts with testUser1', async () => {
+      const pages = await Page.findManageableListWithDescendants(
+        parentPage,
+        testUser1,
+      );
 
       // assert totalCount
       expect(pages.length).toEqual(3);
 
       // assert paths
-      const pagePaths = await pages.map((page) => { return page.path });
+      const pagePaths = await pages.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/grant/groupacl');
       expect(pagePaths).toContainEqual('/grant/public');
       expect(pagePaths).toContainEqual('/grant');
     });
 
-    test('can retrieve only public page which starts with testUser2', async() => {
-      const pages = await Page.findManageableListWithDescendants(parentPage, testUser2);
+    test('can retrieve only public page which starts with testUser2', async () => {
+      const pages = await Page.findManageableListWithDescendants(
+        parentPage,
+        testUser2,
+      );
 
       // assert totalCount
       expect(pages.length).toEqual(2);
 
       // assert paths
-      const pagePaths = await pages.map((page) => { return page.path });
+      const pagePaths = await pages.map((page) => {
+        return page.path;
+      });
       expect(pagePaths).toContainEqual('/grant/public');
       expect(pagePaths).toContainEqual('/grant');
     });
 
-    test('can retrieve only public page which starts without user', async() => {
-      const pages = await Page.findManageableListWithDescendants(parentPage, null);
+    test('can retrieve only public page which starts without user', async () => {
+      const pages = await Page.findManageableListWithDescendants(
+        parentPage,
+        null,
+      );
 
       // assert totalCount
       expect(pages).toBeNull();
     });
   });
-
 });

+ 38 - 12
apps/app/test/integration/models/update-post.test.js

@@ -1,16 +1,32 @@
 import UpdatePost from '../../../src/server/models/update-post';
 
 describe('UpdatePost', () => {
-
   describe('.createPrefixesByPathPattern', () => {
     describe('with a path', () => {
       test('should return right patternPrfixes', () => {
-        expect(UpdatePost.createPrefixesByPathPattern('/*')).toEqual(['*', '*']);
-        expect(UpdatePost.createPrefixesByPathPattern('/user/*/日報*')).toEqual(['user', '*']);
-        expect(UpdatePost.createPrefixesByPathPattern('/project/hoge/*')).toEqual(['project', 'hoge']);
-        expect(UpdatePost.createPrefixesByPathPattern('/*/MTG/*')).toEqual(['*', 'MTG']);
-        expect(UpdatePost.createPrefixesByPathPattern('自己紹介')).toEqual(['*', '*']);
-        expect(UpdatePost.createPrefixesByPathPattern('/user/aoi/メモ/2016/02/10/xxx')).toEqual(['user', 'aoi']);
+        expect(UpdatePost.createPrefixesByPathPattern('/*')).toEqual([
+          '*',
+          '*',
+        ]);
+        expect(UpdatePost.createPrefixesByPathPattern('/user/*/日報*')).toEqual(
+          ['user', '*'],
+        );
+        expect(
+          UpdatePost.createPrefixesByPathPattern('/project/hoge/*'),
+        ).toEqual(['project', 'hoge']);
+        expect(UpdatePost.createPrefixesByPathPattern('/*/MTG/*')).toEqual([
+          '*',
+          'MTG',
+        ]);
+        expect(UpdatePost.createPrefixesByPathPattern('自己紹介')).toEqual([
+          '*',
+          '*',
+        ]);
+        expect(
+          UpdatePost.createPrefixesByPathPattern(
+            '/user/aoi/メモ/2016/02/10/xxx',
+          ),
+        ).toEqual(['user', 'aoi']);
       });
     });
   });
@@ -19,11 +35,21 @@ describe('UpdatePost', () => {
     describe('with a pattern', () => {
       test('should return right regexp', () => {
         expect(UpdatePost.getRegExpByPattern('/*')).toEqual(/^\/.*/);
-        expect(UpdatePost.getRegExpByPattern('/user/*/日報*')).toEqual(/^\/user\/.*\/日報.*/);
-        expect(UpdatePost.getRegExpByPattern('/project/hoge/*')).toEqual(/^\/project\/hoge\/.*/);
-        expect(UpdatePost.getRegExpByPattern('/*/MTG/*')).toEqual(/^\/.*\/MTG\/.*/);
-        expect(UpdatePost.getRegExpByPattern('自己紹介')).toEqual(/^\/.*自己紹介.*/);
-        expect(UpdatePost.getRegExpByPattern('/user/aoi/メモ/2016/02/10/xxx')).toEqual(/^\/user\/aoi\/メモ\/2016\/02\/10\/xxx/);
+        expect(UpdatePost.getRegExpByPattern('/user/*/日報*')).toEqual(
+          /^\/user\/.*\/日報.*/,
+        );
+        expect(UpdatePost.getRegExpByPattern('/project/hoge/*')).toEqual(
+          /^\/project\/hoge\/.*/,
+        );
+        expect(UpdatePost.getRegExpByPattern('/*/MTG/*')).toEqual(
+          /^\/.*\/MTG\/.*/,
+        );
+        expect(UpdatePost.getRegExpByPattern('自己紹介')).toEqual(
+          /^\/.*自己紹介.*/,
+        );
+        expect(
+          UpdatePost.getRegExpByPattern('/user/aoi/メモ/2016/02/10/xxx'),
+        ).toEqual(/^\/user\/aoi\/メモ\/2016\/02\/10\/xxx/);
       });
     });
   });

+ 47 - 25
apps/app/test/integration/models/user.test.js

@@ -2,7 +2,6 @@ const mongoose = require('mongoose');
 
 const { getInstance } = require('../setup-crowi');
 
-
 describe('User', () => {
   // eslint-disable-next-line no-unused-vars
   let crowi;
@@ -10,7 +9,7 @@ describe('User', () => {
 
   let adminusertestToBeRemovedId;
 
-  beforeAll(async() => {
+  beforeAll(async () => {
     crowi = await getInstance();
     User = mongoose.model('User');
 
@@ -52,7 +51,9 @@ describe('User', () => {
     ]);
 
     // delete adminusertestToBeRemoved
-    const adminusertestToBeRemoved = await User.findOne({ username: 'adminusertestToBeRemoved' });
+    const adminusertestToBeRemoved = await User.findOne({
+      username: 'adminusertestToBeRemoved',
+    });
     adminusertestToBeRemovedId = adminusertestToBeRemoved._id;
     await adminusertestToBeRemoved.statusDelete();
   });
@@ -60,28 +61,35 @@ describe('User', () => {
   describe('Create and Find.', () => {
     describe('The user', () => {
       test('should created with createUserByEmailAndPassword', (done) => {
-        User.createUserByEmailAndPassword('Example2 for User Test', 'usertest2', 'usertest2@example.com', 'usertest2pass', 'en_US', (err, userData) => {
-          expect(err).toBeNull();
-          expect(userData).toBeInstanceOf(User);
-          expect(userData.name).toBe('Example2 for User Test');
-          done();
-        });
+        User.createUserByEmailAndPassword(
+          'Example2 for User Test',
+          'usertest2',
+          'usertest2@example.com',
+          'usertest2pass',
+          'en_US',
+          (err, userData) => {
+            expect(err).toBeNull();
+            expect(userData).toBeInstanceOf(User);
+            expect(userData.name).toBe('Example2 for User Test');
+            done();
+          },
+        );
       });
 
-      test('should be found by findUserByUsername', async() => {
+      test('should be found by findUserByUsername', async () => {
         const user = await User.findUserByUsername('usertest');
         expect(user).toBeInstanceOf(User);
         expect(user.name).toBe('Example for User Test');
       });
     });
-
   });
 
   describe('Delete.', () => {
-
     describe('Deleted users', () => {
-      test('should have correct attributes', async() => {
-        const adminusertestToBeRemoved = await User.findOne({ _id: adminusertestToBeRemovedId });
+      test('should have correct attributes', async () => {
+        const adminusertestToBeRemoved = await User.findOne({
+          _id: adminusertestToBeRemovedId,
+        });
 
         expect(adminusertestToBeRemoved).toBeInstanceOf(User);
         expect(adminusertestToBeRemoved.name).toBe('');
@@ -94,22 +102,36 @@ describe('User', () => {
   });
 
   describe('User.findAdmins', () => {
-    test('should retrieves only active users', async() => {
+    test('should retrieves only active users', async () => {
       const users = await User.findAdmins();
-      const adminusertestActive = users.find(user => user.username === 'adminusertest1');
-      const adminusertestSuspended = users.find(user => user.username === 'adminusertest2');
-      const adminusertestToBeRemoved = users.find(user => user._id.toString() === adminusertestToBeRemovedId.toString());
+      const adminusertestActive = users.find(
+        (user) => user.username === 'adminusertest1',
+      );
+      const adminusertestSuspended = users.find(
+        (user) => user.username === 'adminusertest2',
+      );
+      const adminusertestToBeRemoved = users.find(
+        (user) => user._id.toString() === adminusertestToBeRemovedId.toString(),
+      );
 
       expect(adminusertestActive).toBeInstanceOf(User);
       expect(adminusertestSuspended).toBeUndefined();
       expect(adminusertestToBeRemoved).toBeUndefined();
     });
 
-    test('with \'includesInactive\' option should retrieves suspended users', async() => {
-      const users = await User.findAdmins({ status: [User.STATUS_ACTIVE, User.STATUS_SUSPENDED] });
-      const adminusertestActive = users.find(user => user.username === 'adminusertest1');
-      const adminusertestSuspended = users.find(user => user.username === 'adminusertest2');
-      const adminusertestToBeRemoved = users.find(user => user._id.toString() === adminusertestToBeRemovedId.toString());
+    test("with 'includesInactive' option should retrieves suspended users", async () => {
+      const users = await User.findAdmins({
+        status: [User.STATUS_ACTIVE, User.STATUS_SUSPENDED],
+      });
+      const adminusertestActive = users.find(
+        (user) => user.username === 'adminusertest1',
+      );
+      const adminusertestSuspended = users.find(
+        (user) => user.username === 'adminusertest2',
+      );
+      const adminusertestToBeRemoved = users.find(
+        (user) => user._id.toString() === adminusertestToBeRemovedId.toString(),
+      );
 
       expect(adminusertestActive).toBeInstanceOf(User);
       expect(adminusertestSuspended).toBeInstanceOf(User);
@@ -119,14 +141,14 @@ describe('User', () => {
 
   describe('User Utilities', () => {
     describe('Get user exists from user page path', () => {
-      test('found', async() => {
+      test('found', async () => {
         const userPagePath = '/user/usertest';
         const isExist = await User.isExistUserByUserPagePath(userPagePath);
 
         expect(isExist).toBe(true);
       });
 
-      test('not found', async() => {
+      test('not found', async () => {
         const userPagePath = '/user/usertest-hoge';
         const isExist = await User.isExistUserByUserPagePath(userPagePath);
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 444 - 124
apps/app/test/integration/models/v5.page.test.js


+ 2 - 4
apps/app/test/integration/setup-crowi.ts

@@ -5,16 +5,14 @@ import { setupModelsDependentOnCrowi } from '../../src/server/crowi/setup-models
 
 let _instance: Crowi;
 
-const initCrowi = async(crowi: Crowi) => {
+const initCrowi = async (crowi: Crowi) => {
   crowi.models = await setupModelsDependentOnCrowi(crowi);
   await crowi.setupConfigManager();
 
   await crowi.setupSocketIoService();
   await crowi.socketIoService.attachServer(new Server()); // attach dummy server
 
-  await Promise.all([
-    crowi.setUpApp(),
-  ]);
+  await Promise.all([crowi.setUpApp()]);
 
   await Promise.all([
     crowi.setupPassport(),

+ 2 - 2
apps/app/test/integration/setup.js

@@ -14,11 +14,11 @@ mongoose.Promise = global.Promise;
 
 jest.setTimeout(30000); // default 5000
 
-beforeAll(async() => {
+beforeAll(async () => {
   await mongoose.connect(getMongoUri(), mongoOptions);
 });
 
-afterAll(async() => {
+afterAll(async () => {
   await mongoose.disconnect();
   gc();
 });

+ 1 - 1
apps/app/test/integration/tsconfig.json

@@ -2,5 +2,5 @@
   "extends": "../../tsconfig.json",
   "compilerOptions": {
     "module": "CommonJS"
-  },
+  }
 }

+ 3 - 5
apps/app/tsconfig.build.client.json

@@ -1,9 +1,7 @@
 {
   "$schema": "http://json.schemastore.org/tsconfig",
   "extends": "./tsconfig.json",
-  "include": [
-    ".next/types/**/*.ts"
-  ],
+  "include": [".next/types/**/*.ts"],
   "compilerOptions": {
     "strict": false,
     "strictNullChecks": true,
@@ -14,8 +12,8 @@
     "baseUrl": ".",
     "paths": {
       "~/*": ["./src/*"],
-      "^/*": ["./*"],
+      "^/*": ["./*"]
     },
-    "plugins": [{"name": "next"}]
+    "plugins": [{ "name": "next" }]
   }
 }

+ 1 - 1
apps/app/tsconfig.build.server.json

@@ -13,7 +13,7 @@
     "baseUrl": ".",
     "paths": {
       "~/*": ["./src/*"],
-      "^/*": ["./*"],
+      "^/*": ["./*"]
     }
   },
   "exclude": [

+ 3 - 9
apps/app/tsconfig.json

@@ -4,14 +4,12 @@
   "compilerOptions": {
     "jsx": "preserve",
     "resolveJsonModule": true,
-    "types": [
-      "vitest/globals"
-    ],
+    "types": ["vitest/globals"],
 
     "baseUrl": ".",
     "paths": {
       "~/*": ["./src/*"],
-      "^/*": ["./*"],
+      "^/*": ["./*"]
     },
 
     /* TODO: remove below flags for strict checking */
@@ -29,11 +27,7 @@
       { "transform": "typescript-transform-paths", "afterDeclarations": true }
     ]
   },
-  "include": [
-    "next-env.d.ts",
-    "config",
-    "src"
-  ],
+  "include": ["next-env.d.ts", "config", "src"],
   "ts-node": {
     "transpileOnly": true,
     "swc": true,

+ 1 - 3
apps/app/vite.styles-prebuilt.config.ts

@@ -6,9 +6,7 @@ export default defineConfig({
   build: {
     outDir: 'src/styles/prebuilt',
     rollupOptions: {
-      input: [
-        '/src/styles/vendor.scss',
-      ],
+      input: ['/src/styles/vendor.scss'],
       output: {
         assetFileNames: '[name].[ext]', // not attach hash
       },

+ 23 - 45
apps/app/vitest.workspace.mts

@@ -1,65 +1,43 @@
 import react from '@vitejs/plugin-react';
 import tsconfigPaths from 'vite-tsconfig-paths';
-import {
-  defineConfig, defineWorkspace, mergeConfig,
-} from 'vitest/config';
+import { defineConfig, defineWorkspace, mergeConfig } from 'vitest/config';
 
 const configShared = defineConfig({
-  plugins: [
-    tsconfigPaths(),
-  ],
+  plugins: [tsconfigPaths()],
   test: {
     clearMocks: true,
     globals: true,
-    exclude: [
-      'test/**',
-      'test-with-vite/**',
-      'playwright/**',
-    ],
+    exclude: ['test/**', 'test-with-vite/**', 'playwright/**'],
   },
 });
 
 export default defineWorkspace([
-
   // unit test
-  mergeConfig(
-    configShared,
-    {
-      test: {
-        name: 'app-unit',
-        environment: 'node',
-        include: ['**/*.spec.{ts,js}'],
-      },
+  mergeConfig(configShared, {
+    test: {
+      name: 'app-unit',
+      environment: 'node',
+      include: ['**/*.spec.{ts,js}'],
     },
-  ),
+  }),
 
   // integration test
-  mergeConfig(
-    configShared,
-    {
-      test: {
-        name: 'app-integration',
-        environment: 'node',
-        include: ['**/*.integ.ts'],
-        setupFiles: [
-          './test-with-vite/setup/mongoms.ts',
-        ],
-      },
+  mergeConfig(configShared, {
+    test: {
+      name: 'app-integration',
+      environment: 'node',
+      include: ['**/*.integ.ts'],
+      setupFiles: ['./test-with-vite/setup/mongoms.ts'],
     },
-  ),
+  }),
 
   // component test
-  mergeConfig(
-    configShared,
-    {
-      plugins: [react()],
-      test: {
-        name: 'app-components',
-        environment: 'happy-dom',
-        include: [
-          '**/*.spec.{tsx,jsx}',
-        ],
-      },
+  mergeConfig(configShared, {
+    plugins: [react()],
+    test: {
+      name: 'app-components',
+      environment: 'happy-dom',
+      include: ['**/*.spec.{tsx,jsx}'],
     },
-  ),
+  }),
 ]);

+ 12 - 2
biome.json

@@ -13,16 +13,26 @@
       "!**/.turbo/**",
       "!**/.vscode/**",
       "!**/turbo.json",
+      "!**/.next/**",
       "!bin/**",
       "!tsconfig.base.json",
       "!**/.devcontainer/**",
       "!**/.eslintrc.js",
       "!**/.stylelintrc.json",
       "!**/package.json",
-      "!apps/app/**",
       "!apps/slackbot-proxy/src/public/bootstrap/**",
       "!packages/editor/**",
-      "!packages/pdf-converter-client/src/index.ts"
+      "!packages/pdf-converter-client/src/index.ts",
+      "!apps/app/bin/**",
+      "!apps/app/config/**",
+      "!apps/app/docker/**",
+      "!apps/app/playwright/**",
+      "!apps/app/public/**",
+      "!apps/app/resource/**",
+      "!apps/app/src/**",
+      "!apps/app/test/integration/service/**",
+      "!apps/app/test-with-vite/**",
+      "!apps/app/tmp/**"
     ]
   },
   "formatter": {

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio