Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] Jest Test e2e #402

Merged
merged 22 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a405362
chore(deps): bump jest from ^27.1.1 to ^29.7.0
rahul-rocket Apr 19, 2024
249b95b
fix: updated gitignore file
rahul-rocket Apr 19, 2024
34431dd
fix: typeorm nested relations query syntax
rahul-rocket Apr 19, 2024
ba62f0c
chore(deps): bump prettier from ^2.4.0 to ^3.2.5
rahul-rocket Apr 20, 2024
3155f79
fix: run prettier for formatting
rahul-rocket Apr 20, 2024
37c71f2
fix: run prettier for formatting
rahul-rocket Apr 20, 2024
0c47d0d
fix: typeorm nested relations query syntax
rahul-rocket Apr 20, 2024
977d9af
fix: get data source connection for e2e testing
rahul-rocket Apr 20, 2024
b09e9b2
fix: run prettier for formatting
rahul-rocket Apr 20, 2024
589b3f2
fix: run prettier for formatting
rahul-rocket Apr 20, 2024
0601077
fix: increased jest testTimeout
rahul-rocket Apr 20, 2024
c0baafb
fix: removed maxWorker for jest
rahul-rocket Apr 20, 2024
a8e3b4d
Merge branch 'develop' into fix/jest-e2e-test
rahul-rocket Jun 24, 2024
3ae84c0
update yarn.lock
rahul-rocket Jun 24, 2024
320fb89
Merge branch 'develop' into fix/jest-e2e-test
rahul-rocket Oct 18, 2024
9d2f066
chore: update yarn.lock
rahul-rocket Oct 18, 2024
4068acb
fix: coderabbitai suggestion
rahul-rocket Oct 18, 2024
16f3500
fix: coderabbitai suggestion
rahul-rocket Oct 18, 2024
182792b
chore: update yarn.lock
rahul-rocket Oct 18, 2024
9d03935
fix: removed console
rahul-rocket Oct 18, 2024
8eb3d11
style: fix code style issues using Prettier
rahul-rocket Oct 18, 2024
e5b950a
fix: updated connection datasource
rahul-rocket Oct 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions api/src/connection/datasource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { DataSource, DataSourceOptions, DefaultNamingStrategy } from 'typeorm';
import * as process from 'process';
import { SnakeNamingStrategy } from '../utils/snake-naming-strategy';

const env = process.env;

/**
* Retrieves the connection options for TypeORM DataSource or TypeORMModule.
* @returns The connection options for TypeORM DataSource or TypeORMModule.
*/
export const dataSourceOptions = (): DataSourceOptions => {
const options: DataSourceOptions = {
type: (env.TR_DB_TYPE as any) || 'mysql',
rahul-rocket marked this conversation as resolved.
Show resolved Hide resolved
host: env.TR_DB_HOST || 'localhost',
port: parseInt(env.TR_DB_PORT, 10) || 3306,
username: env.TR_DB_USER || 'root',
password: env.TR_DB_PASSWORD || '',
database: env.TR_DB_DATABASE || 'tr_dev',
charset: 'utf8mb4',
synchronize: false,
logging: false,
entities: ['src/entity/*.entity*'],
migrations: ['src/migrations/*'],
rahul-rocket marked this conversation as resolved.
Show resolved Hide resolved
namingStrategy: env.TR_DB_TYPE === 'postgres' ? new SnakeNamingStrategy() : new DefaultNamingStrategy(),
rahul-rocket marked this conversation as resolved.
Show resolved Hide resolved
};
return options;
};

/**
* Creates and initializes a TypeORM DataSource instance with the provided configuration options.
* @returns Initialized TypeORM DataSource instance.
*/
export const getDataSourceConnection = async (): Promise<DataSource> => {
const dataSource = new DataSource(dataSourceOptions());

try {
if (!dataSource.isInitialized) {
await dataSource.initialize();
}
} catch (error) {
console.error(error?.message);
}

return dataSource;
};
rahul-rocket marked this conversation as resolved.
Show resolved Hide resolved
8 changes: 6 additions & 2 deletions api/src/controllers/exports.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ export class ExportsController {
// Ensure locale is requested project locale
const projectLocale = await this.projectLocaleRepo.findOne({
where: {
project: membership.project,
project: {
id: membership.project.id,
},
rahul-rocket marked this conversation as resolved.
Show resolved Hide resolved
locale: {
code: query.locale,
},
Expand Down Expand Up @@ -98,7 +100,9 @@ export class ExportsController {
if (query.fallbackLocale) {
const fallbackProjectLocale = await this.projectLocaleRepo.findOne({
where: {
project: membership.project,
project: {
id: membership.project.id,
},
locale: {
code: query.fallbackLocale,
},
Expand Down
4 changes: 3 additions & 1 deletion api/src/controllers/import.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ export class ImportController {
// Extract into service for creating project locales
projectLocale = this.projectLocaleRepo.create({
locale: locale,
project: membership.project,
project: {
id: membership.project.id,
},
});
projectLocale = await entityManager.save(ProjectLocale, projectLocale);
await entityManager.increment(Project, { id: membership.project.id }, 'localesCount', 1);
Expand Down
24 changes: 13 additions & 11 deletions api/src/controllers/project-label.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export default class ProjectLabelController {
async delete(@Req() req, @Param('projectId') projectId: string, @Param('labelId') labelId: string) {
const user = this.auth.getRequestUserOrClient(req);
const membership = await this.auth.authorizeProjectAction(user, projectId, ProjectAction.DeleteLabel);
const label = await this.labelRepo.findOneOrFail({ where: { id: labelId, project: membership.project } });
const label = await this.labelRepo.findOneOrFail({ where: { id: labelId, project: { id: membership.project.id } } });
await this.labelRepo.remove(label);
}

Expand All @@ -122,8 +122,8 @@ export default class ProjectLabelController {
const user = this.auth.getRequestUserOrClient(req);
const membership = await this.auth.authorizeProjectAction(user, projectId, ProjectAction.EditLabel);

const label = await this.labelRepo.findOneOrFail({ where: { id: labelId, project: membership.project } });
const term = await this.termsRepo.findOneOrFail({ where: { id: termId, project: membership.project }, relations: ['labels'] });
const label = await this.labelRepo.findOneOrFail({ where: { id: labelId, project: { id: membership.project.id } } });
const term = await this.termsRepo.findOneOrFail({ where: { id: termId, project: { id: membership.project.id } }, relations: ['labels'] });

term.labels.push(label);

Expand All @@ -149,8 +149,8 @@ export default class ProjectLabelController {
const user = this.auth.getRequestUserOrClient(req);
const membership = await this.auth.authorizeProjectAction(user, projectId, ProjectAction.EditLabel);

const label = await this.labelRepo.findOneOrFail({ where: { id: labelId, project: membership.project } });
const term = await this.termsRepo.findOneOrFail({ where: { id: termId, project: membership.project }, relations: ['labels'] });
const label = await this.labelRepo.findOneOrFail({ where: { id: labelId, project: { id: membership.project.id } } });
const term = await this.termsRepo.findOneOrFail({ where: { id: termId, project: { id: membership.project.id } }, relations: ['labels'] });

term.labels = term.labels.filter(t => t.id !== label.id);

Expand All @@ -174,19 +174,21 @@ export default class ProjectLabelController {
const user = this.auth.getRequestUserOrClient(req);
const membership = await this.auth.authorizeProjectAction(user, projectId, ProjectAction.EditLabel);

const label = await this.labelRepo.findOneOrFail({ where: { id: labelId, project: membership.project } });
const label = await this.labelRepo.findOneOrFail({ where: { id: labelId, project: { id: membership.project.id } } });

const projectLocale = await this.projectLocaleRepo.findOneOrFail({
where: {
project: membership.project,
project: {
id: membership.project.id,
},
locale: {
code: localeCode,
},
},
});

const translation = await this.translationsRepo.findOneOrFail({
where: { termId: termId, projectLocale: projectLocale },
where: { termId: termId, projectLocale: { id: projectLocale.id } },
relations: ['labels'],
});

Expand All @@ -212,19 +214,19 @@ export default class ProjectLabelController {
const user = this.auth.getRequestUserOrClient(req);
const membership = await this.auth.authorizeProjectAction(user, projectId, ProjectAction.EditLabel);

const label = await this.labelRepo.findOneOrFail({ where: { id: labelId, project: membership.project } });
const label = await this.labelRepo.findOneOrFail({ where: { id: labelId, project: { id: membership.project.id } } });

const projectLocale = await this.projectLocaleRepo.findOneOrFail({
where: {
project: membership.project,
project: { id: membership.project.id },
locale: {
code: localeCode,
},
},
});

const translation = await this.translationsRepo.findOneOrFail({
where: { termId: termId, projectLocale: projectLocale },
where: { termId: termId, projectLocale: { id: projectLocale.id } },
relations: ['labels'],
});

Expand Down
2 changes: 1 addition & 1 deletion api/src/controllers/project-stats.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default class ProjectStatsController {
const membership = await this.auth.authorizeProjectAction(user, projectId, ProjectAction.ViewTranslation);
const locales = await this.projectLocaleRepo.find({
where: {
project: membership.project,
project: { id: membership.project.id },
},
relations: ['locale'],
});
Expand Down
5 changes: 4 additions & 1 deletion api/src/controllers/project-user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import AuthorizationService from '../services/authorization.service';
@ApiOAuth2([])
@ApiTags('Project Users')
export default class ProjectUserController {
constructor(private auth: AuthorizationService, @InjectRepository(ProjectUser) private projectUserRepo: Repository<ProjectUser>) {}
constructor(
private auth: AuthorizationService,
@InjectRepository(ProjectUser) private projectUserRepo: Repository<ProjectUser>,
) {}

@Get(':projectId/users')
@ApiOperation({ summary: 'List all users with access to a project' })
Expand Down
6 changes: 4 additions & 2 deletions api/src/controllers/term.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ export default class TermController {

const projectLocales = await this.projectLocaleRepo.find({
where: {
project: membership.project,
project: {
id: membership.project.id,
},
},
});

Expand Down Expand Up @@ -143,7 +145,7 @@ export default class TermController {
const user = this.auth.getRequestUserOrClient(req);
const membership = await this.auth.authorizeProjectAction(user, projectId, ProjectAction.DeleteTerm);
await this.termRepo.manager.transaction(async entityManager => {
const term = await entityManager.findOneOrFail(Term, { where: { id: termId, project: membership.project } });
const term = await entityManager.findOneOrFail(Term, { where: { id: termId, project: { id: membership.project.id } } });
await entityManager.remove(term);
await entityManager.decrement(Project, { id: membership.project.id }, 'termsCount', 1);
});
Expand Down
20 changes: 13 additions & 7 deletions api/src/controllers/translation.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default class TranslationController {
const membership = await this.auth.authorizeProjectAction(user, projectId, ProjectAction.ViewTranslation);
const locales = await this.projectLocaleRepo.find({
where: {
project: membership.project,
project: { id: membership.project.id },
},
relations: ['locale'],
});
Expand Down Expand Up @@ -95,8 +95,10 @@ export default class TranslationController {
});

const result = await this.projectLocaleRepo.findOneByOrFail({
locale,
project: membership.project,
locale: {
code: locale.code,
},
project: { id: membership.project.id },
});

return {
Expand Down Expand Up @@ -126,7 +128,7 @@ export default class TranslationController {
// Ensure locale is requested project locale
const projectLocale = await this.projectLocaleRepo.findOneOrFail({
where: {
project: membership.project,
project: { id: membership.project.id },
locale: {
code: localeCode,
},
Expand All @@ -135,7 +137,9 @@ export default class TranslationController {
try {
const translations = await this.translationRepo.find({
where: {
projectLocale,
projectLocale: {
id: projectLocale.id,
},
},
relations: ['term', 'labels'],
});
Expand Down Expand Up @@ -186,7 +190,9 @@ export default class TranslationController {
let translation = await this.translationRepo.findOne({
where: {
termId: term.id,
projectLocale: projectLocale,
projectLocale: {
id: projectLocale.id,
},
},
relations: ['labels'],
});
Expand Down Expand Up @@ -231,7 +237,7 @@ export default class TranslationController {
await this.projectLocaleRepo.manager.transaction(async entityManager => {
const projectLocale = await entityManager.findOneOrFail(ProjectLocale, {
where: {
project: membership.project,
project: { id: membership.project.id },
locale: {
code: localeCode,
},
Expand Down
5 changes: 4 additions & 1 deletion api/src/controllers/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import { UserService } from '../services/user.service';
@ApiOAuth2([])
@ApiTags('Users')
export default class UserController {
constructor(private auth: AuthorizationService, private userService: UserService) {}
constructor(
private auth: AuthorizationService,
private userService: UserService,
) {}

@Get('me')
@ApiOperation({ summary: `Get the current user's profile` })
Expand Down
10 changes: 7 additions & 3 deletions api/test/jest-e2e.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
{
"moduleFileExtensions": ["js", "json", "ts"],
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": ".",
"testEnvironment": "node",
"testTimeout": 60000,
"testTimeout": 120000,
"testRegex": ".e2e-spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
}
}
}
14 changes: 8 additions & 6 deletions api/test/user.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Connection } from 'typeorm';
import { DataSource } from 'typeorm';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { getRepository } from 'typeorm';
import { getDataSourceConnection } from '../src/connection/datasource';
import { ProjectLocale } from '../src/entity/project-locale.entity';
import { Project } from '../src/entity/project.entity';
import { Term } from '../src/entity/term.entity';
Expand All @@ -10,6 +10,7 @@ import { createAndMigrateApp, createTestProject, signupTestUser, TestingProject,

describe('UserController (e2e)', () => {
let app: INestApplication;
let connection: DataSource;
rahul-rocket marked this conversation as resolved.
Show resolved Hide resolved
let testingUser: TestingUser;
let testingUser2: TestingUser;
let testingUser3: TestingUser;
Expand All @@ -18,6 +19,7 @@ describe('UserController (e2e)', () => {

beforeEach(async () => {
app = await createAndMigrateApp();
connection = await getDataSourceConnection();
testingUser = await signupTestUser(app);
testingUser2 = await signupTestUser(app, '[email protected]');
testingUser3 = await signupTestUser(app, '[email protected]');
Expand Down Expand Up @@ -224,15 +226,15 @@ describe('UserController (e2e)', () => {

await request(app.getHttpServer()).get('/api/v1/projects').set('Authorization', `Bearer ${testingUser3.accessToken}`).expect(401);

const project = await getRepository(Project).findOneBy({ id: testProject.id });
const project = await connection.getRepository(Project).findOneBy({ id: testProject.id });
expect(project).toBeDefined();
expect(project.id).toEqual(testProject.id);

const term = await getRepository(Term).findOneBy({ id: termId });
const term = await connection.getRepository(Term).findOneBy({ id: termId });
expect(term).toBeDefined();
expect(term.id).toEqual(termId);

const projectLocales = await getRepository(ProjectLocale).find({
const projectLocales = await connection.getRepository(ProjectLocale).find({
where: { project: { id: testProject.id } },
relations: ['locale'],
});
Expand All @@ -242,7 +244,7 @@ describe('UserController (e2e)', () => {
});

afterEach(async () => {
await app.get(Connection).close();
await connection.destroy();
await app.close();
});
});
33 changes: 26 additions & 7 deletions api/test/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,38 @@ export async function createTestProjectClient(
return result;
}

/**
* Creates and initializes a Nest application, drops the database, runs migrations, and returns the initialized application.
* @returns The initialized Nest application.
*/
export async function createAndMigrateApp(): Promise<INestApplication> {
const moduleFixture = await Test.createTestingModule({
imports: [AppModule],
}).compile();
// Compile the testing module for the AppModule
const moduleFixture = await Test.createTestingModule({ imports: [AppModule] }).compile();

let app = moduleFixture.createNestApplication<NestExpressApplication>(new ExpressAdapter());
// Create a Nest application instance using the ExpressAdapter
const app = moduleFixture.createNestApplication<NestExpressApplication>(new ExpressAdapter());

// Apply any middleware, pipes, and filters to the application
addPipesAndFilters(app);
app = await app.init();

// Initialize the application
await app.init();

// Get the database connection from the application
const connection = app.get(Connection);
await connection.dropDatabase();
await connection.runMigrations();

try {
// Drop the database
await connection.dropDatabase();

// Run migrations
await connection.runMigrations();
} catch (error) {
// Handle errors if dropping the database or running migrations fails
console.error('Error occurred while dropping database or running migrations:', error);
}
rahul-rocket marked this conversation as resolved.
Show resolved Hide resolved

// Return the initialized application
return app;
}

Expand Down
1 change: 1 addition & 0 deletions webapp/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
!.vscode/extensions.json

# misc
/.cache
/.sass-cache
/connect.lock
/coverage
Expand Down
Loading