mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-14 01:16:17 +02:00
Merge pull request #1095 from Unleash/feat/splash
create splash migration store and service file
This commit is contained in:
commit
67f7969b84
@ -29,6 +29,7 @@ import EnvironmentStore from './environment-store';
|
|||||||
import FeatureTagStore from './feature-tag-store';
|
import FeatureTagStore from './feature-tag-store';
|
||||||
import { FeatureEnvironmentStore } from './feature-environment-store';
|
import { FeatureEnvironmentStore } from './feature-environment-store';
|
||||||
import { ClientMetricsStoreV2 } from './client-metrics-store-v2';
|
import { ClientMetricsStoreV2 } from './client-metrics-store-v2';
|
||||||
|
import UserSplashStore from './user-splash-store';
|
||||||
|
|
||||||
export const createStores = (
|
export const createStores = (
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
@ -85,6 +86,7 @@ export const createStores = (
|
|||||||
eventBus,
|
eventBus,
|
||||||
getLogger,
|
getLogger,
|
||||||
),
|
),
|
||||||
|
userSplashStore: new UserSplashStore(db, eventBus, getLogger),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
105
src/lib/db/user-splash-store.ts
Normal file
105
src/lib/db/user-splash-store.ts
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
import { LogProvider, Logger } from '../logger';
|
||||||
|
import {
|
||||||
|
IUserSplash,
|
||||||
|
IUserSplashKey,
|
||||||
|
IUserSplashStore,
|
||||||
|
} from '../types/stores/user-splash-store';
|
||||||
|
|
||||||
|
const COLUMNS = ['user_id', 'splash_id', 'seen'];
|
||||||
|
const TABLE = 'user_splash';
|
||||||
|
|
||||||
|
interface IUserSplashTable {
|
||||||
|
seen?: boolean;
|
||||||
|
splash_id: string;
|
||||||
|
user_id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fieldToRow = (fields: IUserSplash): IUserSplashTable => ({
|
||||||
|
seen: fields.seen,
|
||||||
|
splash_id: fields.splashId,
|
||||||
|
user_id: fields.userId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const rowToField = (row: IUserSplashTable): IUserSplash => ({
|
||||||
|
seen: row.seen,
|
||||||
|
splashId: row.splash_id,
|
||||||
|
userId: row.user_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default class UserSplashStore implements IUserSplashStore {
|
||||||
|
private db: Knex;
|
||||||
|
|
||||||
|
private logger: Logger;
|
||||||
|
|
||||||
|
constructor(db: Knex, eventBus: EventEmitter, getLogger: LogProvider) {
|
||||||
|
this.db = db;
|
||||||
|
this.logger = getLogger('user-splash-store.ts');
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllUserSplashs(userId: number): Promise<IUserSplash[]> {
|
||||||
|
const userSplash = await this.db
|
||||||
|
.table<IUserSplashTable>(TABLE)
|
||||||
|
.select()
|
||||||
|
.where({ user_id: userId });
|
||||||
|
|
||||||
|
return userSplash.map(rowToField);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSplash(userId: number, splashId: string): Promise<IUserSplash> {
|
||||||
|
const userSplash = await this.db
|
||||||
|
.table<IUserSplashTable>(TABLE)
|
||||||
|
.select()
|
||||||
|
.where({ user_id: userId, splash_id: splashId })
|
||||||
|
.first();
|
||||||
|
|
||||||
|
return rowToField(userSplash);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateSplash(splash: IUserSplash): Promise<IUserSplash> {
|
||||||
|
const insertedSplash = await this.db
|
||||||
|
.table<IUserSplashTable>(TABLE)
|
||||||
|
.insert(fieldToRow(splash))
|
||||||
|
.onConflict(['user_id', 'splash_id'])
|
||||||
|
.merge()
|
||||||
|
.returning(COLUMNS);
|
||||||
|
|
||||||
|
return rowToField(insertedSplash[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete({ userId, splashId }: IUserSplashKey): Promise<void> {
|
||||||
|
await this.db(TABLE)
|
||||||
|
.where({ user_id: userId, splash_id: splashId })
|
||||||
|
.del();
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteAll(): Promise<void> {
|
||||||
|
await this.db(TABLE).del();
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy(): void {}
|
||||||
|
|
||||||
|
async exists({ userId, splashId }: IUserSplashKey): Promise<boolean> {
|
||||||
|
const result = await this.db.raw(
|
||||||
|
`SELECT EXISTS (SELECT 1 FROM ${TABLE} WHERE user_id = ? AND splash_id = ?) AS present`,
|
||||||
|
[userId, splashId],
|
||||||
|
);
|
||||||
|
const { present } = result.rows[0];
|
||||||
|
return present;
|
||||||
|
}
|
||||||
|
|
||||||
|
async get({ userId, splashId }: IUserSplashKey): Promise<IUserSplash> {
|
||||||
|
return this.getSplash(userId, splashId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAll(): Promise<IUserSplash[]> {
|
||||||
|
const userSplashs = await this.db
|
||||||
|
.table<IUserSplashTable>(TABLE)
|
||||||
|
.select();
|
||||||
|
|
||||||
|
return userSplashs.map(rowToField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = UserSplashStore;
|
@ -21,6 +21,7 @@ import ApiTokenController from './api-token-controller';
|
|||||||
import UserAdminController from './user-admin';
|
import UserAdminController from './user-admin';
|
||||||
import EmailController from './email';
|
import EmailController from './email';
|
||||||
import UserFeedbackController from './user-feedback-controller';
|
import UserFeedbackController from './user-feedback-controller';
|
||||||
|
import UserSplashController from './user-splash-controller';
|
||||||
import ProjectApi from './project';
|
import ProjectApi from './project';
|
||||||
import { EnvironmentsController } from './environments-controller';
|
import { EnvironmentsController } from './environments-controller';
|
||||||
|
|
||||||
@ -92,6 +93,10 @@ class AdminApi extends Controller {
|
|||||||
'/environments',
|
'/environments',
|
||||||
new EnvironmentsController(config, services).router,
|
new EnvironmentsController(config, services).router,
|
||||||
);
|
);
|
||||||
|
this.app.use(
|
||||||
|
'/splash',
|
||||||
|
new UserSplashController(config, services).router,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
index(req, res) {
|
index(req, res) {
|
||||||
|
49
src/lib/routes/admin-api/user-splash-controller.ts
Normal file
49
src/lib/routes/admin-api/user-splash-controller.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { Response } from 'express';
|
||||||
|
|
||||||
|
import Controller from '../controller';
|
||||||
|
import { Logger } from '../../logger';
|
||||||
|
import { IUnleashConfig } from '../../types/option';
|
||||||
|
import { IUnleashServices } from '../../types/services';
|
||||||
|
import UserSplashService from '../../services/user-splash-service';
|
||||||
|
import { IAuthRequest } from '../unleash-types';
|
||||||
|
|
||||||
|
interface ISplashBody {
|
||||||
|
seen: boolean;
|
||||||
|
splashId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserSplashController extends Controller {
|
||||||
|
private logger: Logger;
|
||||||
|
|
||||||
|
private userSplashService: UserSplashService;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
config: IUnleashConfig,
|
||||||
|
{ userSplashService }: Pick<IUnleashServices, 'userSplashService'>,
|
||||||
|
) {
|
||||||
|
super(config);
|
||||||
|
this.logger = config.getLogger('splash-controller.ts');
|
||||||
|
this.userSplashService = userSplashService;
|
||||||
|
|
||||||
|
this.post('/:id', this.updateSplashSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updateSplashSettings(
|
||||||
|
req: IAuthRequest<any, any, ISplashBody, any>,
|
||||||
|
res: Response,
|
||||||
|
): Promise<void> {
|
||||||
|
const { user } = req;
|
||||||
|
const { id } = req.params;
|
||||||
|
|
||||||
|
const splash = {
|
||||||
|
splashId: id,
|
||||||
|
userId: user.id,
|
||||||
|
seen: true,
|
||||||
|
};
|
||||||
|
const updated = await this.userSplashService.updateSplash(splash);
|
||||||
|
res.json(updated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = UserSplashController;
|
||||||
|
export default UserSplashController;
|
@ -7,6 +7,7 @@ import { IUnleashServices } from '../../types/services';
|
|||||||
import UserService from '../../services/user-service';
|
import UserService from '../../services/user-service';
|
||||||
import SessionService from '../../services/session-service';
|
import SessionService from '../../services/session-service';
|
||||||
import UserFeedbackService from '../../services/user-feedback-service';
|
import UserFeedbackService from '../../services/user-feedback-service';
|
||||||
|
import UserSplashService from '../../services/user-splash-service';
|
||||||
|
|
||||||
interface IChangeUserRequest {
|
interface IChangeUserRequest {
|
||||||
password: string;
|
password: string;
|
||||||
@ -22,6 +23,8 @@ class UserController extends Controller {
|
|||||||
|
|
||||||
private sessionService: SessionService;
|
private sessionService: SessionService;
|
||||||
|
|
||||||
|
private userSplashService: UserSplashService;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
{
|
{
|
||||||
@ -29,12 +32,14 @@ class UserController extends Controller {
|
|||||||
userService,
|
userService,
|
||||||
sessionService,
|
sessionService,
|
||||||
userFeedbackService,
|
userFeedbackService,
|
||||||
|
userSplashService,
|
||||||
}: Pick<
|
}: Pick<
|
||||||
IUnleashServices,
|
IUnleashServices,
|
||||||
| 'accessService'
|
| 'accessService'
|
||||||
| 'userService'
|
| 'userService'
|
||||||
| 'sessionService'
|
| 'sessionService'
|
||||||
| 'userFeedbackService'
|
| 'userFeedbackService'
|
||||||
|
| 'userSplashService'
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
super(config);
|
super(config);
|
||||||
@ -42,6 +47,7 @@ class UserController extends Controller {
|
|||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
this.sessionService = sessionService;
|
this.sessionService = sessionService;
|
||||||
this.userFeedbackService = userFeedbackService;
|
this.userFeedbackService = userFeedbackService;
|
||||||
|
this.userSplashService = userSplashService;
|
||||||
|
|
||||||
this.get('/', this.getUser);
|
this.get('/', this.getUser);
|
||||||
this.post('/change-password', this.updateUserPass);
|
this.post('/change-password', this.updateUserPass);
|
||||||
@ -57,11 +63,15 @@ class UserController extends Controller {
|
|||||||
const feedback = await this.userFeedbackService.getAllUserFeedback(
|
const feedback = await this.userFeedbackService.getAllUserFeedback(
|
||||||
user,
|
user,
|
||||||
);
|
);
|
||||||
|
const splash = await this.userSplashService.getAllUserSplashs(user);
|
||||||
|
|
||||||
// TODO: remove this line after we remove it from db.
|
// TODO: remove this line after we remove it from db.
|
||||||
delete user.permissions;
|
delete user.permissions;
|
||||||
|
|
||||||
return res.status(200).json({ user, permissions, feedback }).end();
|
return res
|
||||||
|
.status(200)
|
||||||
|
.json({ user, permissions, feedback, splash })
|
||||||
|
.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateUserPass(
|
async updateUserPass(
|
||||||
|
@ -27,6 +27,7 @@ import FeatureToggleService from './feature-toggle-service';
|
|||||||
import EnvironmentService from './environment-service';
|
import EnvironmentService from './environment-service';
|
||||||
import FeatureTagService from './feature-tag-service';
|
import FeatureTagService from './feature-tag-service';
|
||||||
import ProjectHealthService from './project-health-service';
|
import ProjectHealthService from './project-health-service';
|
||||||
|
import UserSplashService from './user-splash-service';
|
||||||
|
|
||||||
export const createServices = (
|
export const createServices = (
|
||||||
stores: IUnleashStores,
|
stores: IUnleashStores,
|
||||||
@ -72,6 +73,7 @@ export const createServices = (
|
|||||||
accessService,
|
accessService,
|
||||||
featureToggleServiceV2,
|
featureToggleServiceV2,
|
||||||
);
|
);
|
||||||
|
const userSplashService = new UserSplashService(stores, config);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
accessService,
|
accessService,
|
||||||
@ -100,6 +102,7 @@ export const createServices = (
|
|||||||
userFeedbackService,
|
userFeedbackService,
|
||||||
featureTagService,
|
featureTagService,
|
||||||
projectHealthService,
|
projectHealthService,
|
||||||
|
userSplashService,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
54
src/lib/services/user-splash-service.ts
Normal file
54
src/lib/services/user-splash-service.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { Logger } from '../logger';
|
||||||
|
import { IUnleashStores } from '../types/stores';
|
||||||
|
import { IUnleashConfig } from '../types/option';
|
||||||
|
import User from '../types/user';
|
||||||
|
import {
|
||||||
|
IUserSplash,
|
||||||
|
IUserSplashStore,
|
||||||
|
} from '../types/stores/user-splash-store';
|
||||||
|
|
||||||
|
export default class UserSplashService {
|
||||||
|
private userSplashStore: IUserSplashStore;
|
||||||
|
|
||||||
|
private logger: Logger;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
{ userSplashStore }: Pick<IUnleashStores, 'userSplashStore'>,
|
||||||
|
{ getLogger }: Pick<IUnleashConfig, 'getLogger'>,
|
||||||
|
) {
|
||||||
|
this.userSplashStore = userSplashStore;
|
||||||
|
this.logger = getLogger('services/user-splash-service.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllUserSplashs(user: User): Promise<Object> {
|
||||||
|
if (user.isAPI) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const splashs = (
|
||||||
|
await this.userSplashStore.getAllUserSplashs(user.id)
|
||||||
|
).reduce(
|
||||||
|
(splashObject, splash) => ({
|
||||||
|
...splashObject,
|
||||||
|
[splash.splashId]: splash.seen,
|
||||||
|
}),
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
return splashs;
|
||||||
|
} catch (err) {
|
||||||
|
this.logger.error(err);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSplash(user_id: number, splash_id: string): Promise<IUserSplash> {
|
||||||
|
return this.userSplashStore.getSplash(user_id, splash_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateSplash(splash: IUserSplash): Promise<IUserSplash> {
|
||||||
|
return this.userSplashStore.updateSplash(splash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = UserSplashService;
|
@ -23,6 +23,7 @@ import EnvironmentService from '../services/environment-service';
|
|||||||
import FeatureTagService from '../services/feature-tag-service';
|
import FeatureTagService from '../services/feature-tag-service';
|
||||||
import ProjectHealthService from '../services/project-health-service';
|
import ProjectHealthService from '../services/project-health-service';
|
||||||
import ClientMetricsServiceV2 from '../services/client-metrics/client-metrics-service-v2';
|
import ClientMetricsServiceV2 from '../services/client-metrics/client-metrics-service-v2';
|
||||||
|
import UserSplashService from '../services/user-splash-service';
|
||||||
|
|
||||||
export interface IUnleashServices {
|
export interface IUnleashServices {
|
||||||
accessService: AccessService;
|
accessService: AccessService;
|
||||||
@ -51,4 +52,5 @@ export interface IUnleashServices {
|
|||||||
userFeedbackService: UserFeedbackService;
|
userFeedbackService: UserFeedbackService;
|
||||||
userService: UserService;
|
userService: UserService;
|
||||||
versionService: VersionService;
|
versionService: VersionService;
|
||||||
|
userSplashService: UserSplashService;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import { IFeatureStrategiesStore } from './stores/feature-strategies-store';
|
|||||||
import { IEnvironmentStore } from './stores/environment-store';
|
import { IEnvironmentStore } from './stores/environment-store';
|
||||||
import { IFeatureToggleClientStore } from './stores/feature-toggle-client-store';
|
import { IFeatureToggleClientStore } from './stores/feature-toggle-client-store';
|
||||||
import { IClientMetricsStoreV2 } from './stores/client-metrics-store-v2';
|
import { IClientMetricsStoreV2 } from './stores/client-metrics-store-v2';
|
||||||
|
import { IUserSplashStore } from './stores/user-splash-store';
|
||||||
|
|
||||||
export interface IUnleashStores {
|
export interface IUnleashStores {
|
||||||
accessStore: IAccessStore;
|
accessStore: IAccessStore;
|
||||||
@ -50,4 +51,5 @@ export interface IUnleashStores {
|
|||||||
tagTypeStore: ITagTypeStore;
|
tagTypeStore: ITagTypeStore;
|
||||||
userFeedbackStore: IUserFeedbackStore;
|
userFeedbackStore: IUserFeedbackStore;
|
||||||
userStore: IUserStore;
|
userStore: IUserStore;
|
||||||
|
userSplashStore: IUserSplashStore;
|
||||||
}
|
}
|
||||||
|
18
src/lib/types/stores/user-splash-store.ts
Normal file
18
src/lib/types/stores/user-splash-store.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { Store } from './store';
|
||||||
|
|
||||||
|
export interface IUserSplash {
|
||||||
|
seen: boolean;
|
||||||
|
splashId: string;
|
||||||
|
userId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUserSplashKey {
|
||||||
|
userId: number;
|
||||||
|
splashId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUserSplashStore extends Store<IUserSplash, IUserSplashKey> {
|
||||||
|
getAllUserSplashs(userId: number): Promise<IUserSplash[]>;
|
||||||
|
getSplash(userId: number, splashId: string): Promise<IUserSplash>;
|
||||||
|
updateSplash(splash: IUserSplash): Promise<IUserSplash>;
|
||||||
|
}
|
25
src/migrations/20211108130333-create-user-splash-table.js
Normal file
25
src/migrations/20211108130333-create-user-splash-table.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
exports.up = function (db, cb) {
|
||||||
|
db.runSql(
|
||||||
|
`
|
||||||
|
CREATE TABLE IF NOT EXISTS user_splash
|
||||||
|
(user_id INTEGER NOT NULL references users (id) ON DELETE CASCADE,
|
||||||
|
splash_id TEXT,
|
||||||
|
seen BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
PRIMARY KEY (user_id, splash_id));
|
||||||
|
CREATE INDEX user_splash_user_id_idx ON user_splash (user_id);
|
||||||
|
`,
|
||||||
|
cb,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (db, cb) {
|
||||||
|
db.runSql(
|
||||||
|
`
|
||||||
|
DROP INDEX user_splash_user_id_idx;
|
||||||
|
DROP TABLE user_splash;
|
||||||
|
`,
|
||||||
|
cb,
|
||||||
|
);
|
||||||
|
};
|
10
src/migrations/20211109103930-add-splash-entry-for-users.js
Normal file
10
src/migrations/20211109103930-add-splash-entry-for-users.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
exports.up = function (db, cb) {
|
||||||
|
db.runSql(
|
||||||
|
`INSERT INTO user_splash(splash_id, user_id, seen) SELECT 'environment', u.id, false FROM users u`,
|
||||||
|
cb,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (db, cb) {
|
||||||
|
db.runSql('DELETE FROM user_splash', cb);
|
||||||
|
};
|
68
src/test/e2e/api/admin/splash.e2e.test.ts
Normal file
68
src/test/e2e/api/admin/splash.e2e.test.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import { Application, NextFunction, Request, Response } from 'express';
|
||||||
|
import { setupAppWithCustomAuth } from '../../helpers/test-helper';
|
||||||
|
import dbInit from '../../helpers/database-init';
|
||||||
|
import getLogger from '../../../fixtures/no-logger';
|
||||||
|
import { IUnleashConfig } from '../../../../lib/types/option';
|
||||||
|
import { IUnleashServices } from '../../../../lib/types/services';
|
||||||
|
|
||||||
|
let stores;
|
||||||
|
let db;
|
||||||
|
let app;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
db = await dbInit('splash_api_serial', getLogger);
|
||||||
|
stores = db.stores;
|
||||||
|
|
||||||
|
const email = 'custom-user@mail.com';
|
||||||
|
|
||||||
|
const preHook = (
|
||||||
|
application: Application,
|
||||||
|
config: IUnleashConfig,
|
||||||
|
{ userService }: IUnleashServices,
|
||||||
|
) => {
|
||||||
|
application.use(
|
||||||
|
'/api/admin/',
|
||||||
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
// @ts-ignore
|
||||||
|
req.user = await userService.loginUserWithoutPassword(
|
||||||
|
email,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
app = await setupAppWithCustomAuth(stores, preHook);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await app.destroy();
|
||||||
|
await db.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it updates splash for user', async () => {
|
||||||
|
expect.assertions(1);
|
||||||
|
|
||||||
|
return app.request
|
||||||
|
.post('/api/admin/splash/environment')
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
.expect((res) => {
|
||||||
|
expect(res.body.seen).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it retrieves splash for user', async () => {
|
||||||
|
expect.assertions(1);
|
||||||
|
|
||||||
|
return app.request
|
||||||
|
.get('/api/admin/user')
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
.expect((res) => {
|
||||||
|
expect(res.body.splash).toStrictEqual({ environment: true });
|
||||||
|
});
|
||||||
|
});
|
82
src/test/e2e/stores/user-splash-store.e2e.test.ts
Normal file
82
src/test/e2e/stores/user-splash-store.e2e.test.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import { IUserSplashStore } from 'lib/types/stores/user-splash-store';
|
||||||
|
import { IUserStore } from 'lib/types/stores/user-store';
|
||||||
|
import dbInit from '../helpers/database-init';
|
||||||
|
import getLogger from '../../fixtures/no-logger';
|
||||||
|
|
||||||
|
let stores;
|
||||||
|
let db;
|
||||||
|
let userSplashStore: IUserSplashStore;
|
||||||
|
let userStore: IUserStore;
|
||||||
|
let currentUser;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
db = await dbInit('user_splash_store', getLogger);
|
||||||
|
stores = db.stores;
|
||||||
|
userSplashStore = stores.userSplashStore;
|
||||||
|
userStore = stores.userStore;
|
||||||
|
currentUser = await userStore.upsert({ email: 'me.feedback@mail.com' });
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await db.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await userSplashStore.deleteAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should create userSplash', async () => {
|
||||||
|
await userSplashStore.updateSplash({
|
||||||
|
splashId: 'some-id',
|
||||||
|
userId: currentUser.id,
|
||||||
|
seen: false,
|
||||||
|
});
|
||||||
|
const userSplashs = await userSplashStore.getAllUserSplashs(currentUser.id);
|
||||||
|
expect(userSplashs).toHaveLength(1);
|
||||||
|
expect(userSplashs[0].splashId).toBe('some-id');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should get userSplash', async () => {
|
||||||
|
await userSplashStore.updateSplash({
|
||||||
|
splashId: 'some-id',
|
||||||
|
userId: currentUser.id,
|
||||||
|
seen: false,
|
||||||
|
});
|
||||||
|
const userSplash = await userSplashStore.getSplash(
|
||||||
|
currentUser.id,
|
||||||
|
'some-id',
|
||||||
|
);
|
||||||
|
expect(userSplash.splashId).toBe('some-id');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should exists', async () => {
|
||||||
|
await userSplashStore.updateSplash({
|
||||||
|
splashId: 'some-id-3',
|
||||||
|
userId: currentUser.id,
|
||||||
|
seen: false,
|
||||||
|
});
|
||||||
|
const exists = await userSplashStore.exists({
|
||||||
|
userId: currentUser.id,
|
||||||
|
splashId: 'some-id-3',
|
||||||
|
});
|
||||||
|
expect(exists).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not exists', async () => {
|
||||||
|
const exists = await userSplashStore.exists({
|
||||||
|
userId: currentUser.id,
|
||||||
|
splashId: 'some-id-not-here',
|
||||||
|
});
|
||||||
|
expect(exists).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should get all userSplashs', async () => {
|
||||||
|
await userSplashStore.updateSplash({
|
||||||
|
splashId: 'some-id-2',
|
||||||
|
userId: currentUser.id,
|
||||||
|
seen: false,
|
||||||
|
});
|
||||||
|
const userSplashs = await userSplashStore.getAll();
|
||||||
|
expect(userSplashs).toHaveLength(1);
|
||||||
|
expect(userSplashs[0].splashId).toBe('some-id-2');
|
||||||
|
});
|
50
src/test/fixtures/fake-user-splash-store.ts
vendored
Normal file
50
src/test/fixtures/fake-user-splash-store.ts
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import {
|
||||||
|
IUserSplashKey,
|
||||||
|
IUserSplash,
|
||||||
|
IUserSplashStore,
|
||||||
|
} from '../../lib/types/stores/user-splash-store';
|
||||||
|
|
||||||
|
export default class FakeUserSplashStore implements IUserSplashStore {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
getAllUserSplashs(userId: number): Promise<IUserSplash[]> {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
getSplash(userId: number, splashId: string): Promise<IUserSplash> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
updateSplash(splash: IUserSplash): Promise<IUserSplash> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
exists(key: IUserSplashKey): Promise<boolean> {
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
get(key: IUserSplashKey): Promise<IUserSplash> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
getAll(): Promise<IUserSplash[]> {
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
delete(key: IUserSplashKey): Promise<void> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
deleteAll(): Promise<void> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
destroy(): void {}
|
||||||
|
}
|
2
src/test/fixtures/store.ts
vendored
2
src/test/fixtures/store.ts
vendored
@ -24,6 +24,7 @@ import FakeFeatureTypeStore from './fake-feature-type-store';
|
|||||||
import FakeResetTokenStore from './fake-reset-token-store';
|
import FakeResetTokenStore from './fake-reset-token-store';
|
||||||
import FakeFeatureToggleClientStore from './fake-feature-toggle-client-store';
|
import FakeFeatureToggleClientStore from './fake-feature-toggle-client-store';
|
||||||
import FakeClientMetricsStoreV2 from './fake-client-metrics-store-v2';
|
import FakeClientMetricsStoreV2 from './fake-client-metrics-store-v2';
|
||||||
|
import FakeUserSplashStore from './fake-user-splash-store';
|
||||||
|
|
||||||
const createStores: () => IUnleashStores = () => {
|
const createStores: () => IUnleashStores = () => {
|
||||||
const db = {
|
const db = {
|
||||||
@ -59,6 +60,7 @@ const createStores: () => IUnleashStores = () => {
|
|||||||
featureTypeStore: new FakeFeatureTypeStore(),
|
featureTypeStore: new FakeFeatureTypeStore(),
|
||||||
resetTokenStore: new FakeResetTokenStore(),
|
resetTokenStore: new FakeResetTokenStore(),
|
||||||
sessionStore: new FakeSessionStore(),
|
sessionStore: new FakeSessionStore(),
|
||||||
|
userSplashStore: new FakeUserSplashStore(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user