Skip to content

Commit

Permalink
Merge branch 'main' into hotfix/add-button-job-page
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexLLKong committed May 28, 2024
2 parents ae443db + 811d3a3 commit 228b95d
Show file tree
Hide file tree
Showing 35 changed files with 6,788 additions and 1,009 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"*.css",
"*.md",
"Dockerfile",
"compose.yaml"
"compose.yaml",
"*.ts"
// Add other file types you want to ignore
],
"plugins": ["@next/eslint-plugin-next"],
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ jobs:
name: playwright-report
path: playwright-report/
retention-days: 30

- name: Create coverage report
run: npx jest --coverage

- name: Upload coverage reports to Codecov
uses: codecov/[email protected]
with:
Expand Down
118 changes: 80 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ Currently, job postings are often restricted to individual platforms, limiting e
**Project Overview:**
Name: job-bank

## Installation

To install the project, clone the repository and run `npm install` to install all dependencies:
**Notes:** This is a React + Next.js project. Please follow these steps to run the project.

- Clone the repository (git clone https://github.com/your-username/job-bank.git). Navigate to root folder (cd job-bank)
- Add the ‘ .env.local’ file to the project.
- Run ‘npm install’ or ‘npm i’ to install dependencies/packages
- Run ‘npm run dev’ to see changes in the local development environment
- To apply EsLint and Prettier before committing, run > npm install or > npm i.
- Make sure to follow the linting rules defined in .eslintrc and .prettierrc.
- Environment variables are loaded using dotenv.
- Run ‘npm run build’ before merging to main to ensure there are no build errors before deployment
- Git commits trigger linting and formatting checks before being committed due to Husky and lint-staged configurations.

**Scripts:**

- dev: Run the development server. (npm run dev OR npm run dev --watch)
Expand All @@ -45,50 +60,77 @@ Name: job-bank
- lint: Lint the codebase using ESLint and Next.js lint rules.
- prepare: Run Husky pre-commit hooks.
- format: Format the code using ESLint and Prettier.
- jest: run jest tests in the e2e folder for testing
- coverage: generates a coverage report after running jest tests

**Husky & Lint-Staged**

- Husky is used for Git hooks, configured to run pre-commit hooks.
- Lint-staged is configured to run ESLint and Prettier on staged files before committing.

**Dependencies:**

- @auth0/nextjs-auth0: Authentication library for Next.js applications.
- @radix-ui/react-checkbox: Component library for checkboxes.
- @radix-ui/react-icons: Component library for icons.
- @radix-ui/react-slot: Component library for slots.
- @sendgrid/mail: Library for sending emails using SendGrid.
- @stripe/stripe-js: Stripe library for client-side integration.
- @tailwindcss/forms: Tailwind CSS plugin for styling form elements.
- auth0: Auth0 client library.
- class-variance-authority: Utility library for class variance.
- clsx: Library for conditionally joining classNames.
- dotenv: Library for loading environment variables.
- lucide-react: Library for Lucide icons.
- mongoose: MongoDB ORM library for Node.js.
- next: React framework for building server-rendered applications.
- react: JavaScript library for building user interfaces.
- react-dom: React library for DOM rendering.
- react-quill: rich text editor component for React
- stripe: Stripe library for server-side integration.
- tailwind-merge: Utility library for merging Tailwind CSS classes.
- tailwindcss-animate: Tailwind CSS plugin for animations.
- node-cron: module for scheduling tasks
**Dependencies**

- `@auth0/nextjs-auth0`: Authentication library for Next.js applications.
- `@heroicons/react`: Heroicons for React.
- `@radix-ui/react-checkbox`: Component library for checkboxes.
- `@radix-ui/react-dialog`: Component library for dialogs.
- `@radix-ui/react-icons`: Component library for icons.
- `@radix-ui/react-label`: Component library for labels.
- `@radix-ui/react-select`: Component library for selects.
- `@radix-ui/react-slot`: Component library for slots.
- `@sendgrid/mail`: Library for sending emails using SendGrid.
- `@stripe/stripe-js`: Stripe library for client-side integration.
- `@tailwindcss/forms`: Tailwind CSS plugin for styling form elements.
- `auth0`: Auth0 client library.
- `axios`: Promise-based HTTP client for the browser and Node.js.
- `babel`: JavaScript compiler.
- `babel-plugin-istanbul`: Babel plugin for code coverage.
- `class-variance-authority`: Utility library for class variance.
- `clsx`: Library for conditionally joining classNames.
- `dotenv`: Library for loading environment variables.
- `lucide-react`: Library for Lucide icons.
- `mongoose`: MongoDB ORM library for Node.js.
- `next`: React framework for building server-rendered applications.
- `node-cron`: Module for scheduling tasks.
- `puppeteer-extra`: Extended version of Puppeteer.
- `puppeteer-extra-plugin-stealth`: Plugin to make Puppeteer stealthier.
- `react`: JavaScript library for building user interfaces.
- `react-dom`: React library for DOM rendering.
- `react-quill`: Rich text editor component for React.
- `stripe`: Stripe library for server-side integration.
- `tailwind-merge`: Utility library for merging Tailwind CSS classes.
- `tailwindcss-animate`: Tailwind CSS plugin for animations.
- `ts-node`: TypeScript execution environment for Node.js.

**DevDependencies:**

- eslint: JavaScript linter.
- eslint-config-next: ESLint configuration for Next.js projects.
- husky: Git hooks manager.
- lint-staged: Run linters on Git staged files.
- postcss: CSS post-processor.
- prettier: Code formatter.
- tailwindcss: Utility-first CSS framework.

**Notes:**

- Use [npm run dev] to start the development server.
- To apply EsLint and Prettier before committing, make sure to run > npm install or > npm i.
- Make sure to follow the linting rules defined in .eslintrc and .prettierrc.
- Environment variables are loaded using dotenv.
Git commits trigger linting and formatting checks before being committed due to Husky and lint-staged configurations.
- `@jest/globals`: Jest globals for TypeScript.
- `@playwright/test`: Playwright testing library.
- `@types/jest`: TypeScript definitions for Jest.
- `@types/node`: TypeScript definitions for Node.js.
- `@types/puppeteer`: TypeScript definitions for Puppeteer.
- `@types/react`: TypeScript definitions for React.
- `eslint`: JavaScript linter.
- `eslint-config-next`: ESLint configuration for Next.js projects.
- `husky`: Git hooks manager.
- `jest`: JavaScript testing framework.
- `jest-playwright-preset`: Jest preset for Playwright.
- `lint-staged`: Run linters on Git staged files.
- `playwright`: End-to-end testing library.
- `postcss`: CSS post-processor.
- `prettier`: Code formatter.
- `puppeteer`: Headless Chrome Node.js API.
- `tailwindcss`: Utility-first CSS framework.
- `ts-jest`: TypeScript preprocessor with source map support for Jest.
- `typescript`: TypeScript language.

**DevOps Notes**

- In the main.yaml, the Docker Image is currently being uploaded to a personal Docker Hub repo (Account name is cassidyboilley099 and repo is job-bank)
- There will be a need to add more qa tests for the app as the current coverage sits around 0% as jest doesnt consider e2e testing.
- The ACTIONS_TOKEN is currently my PAT, a new token will need to be made. The same applies to the DOCKER_PASSWORD and DOCKER_USERNAME.
To modify these go to the repo -> Settings -> Secrets and Variables -> Actions
^^
This will require admin access to the repository

- Testing is done through Playwright and Jest. Ideally tests should be made with Jest so that coverage can be done. However playwright is easier to use but doesn't currently have coverage reports.
2 changes: 1 addition & 1 deletion cron/sendEmail.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const sendEmail = async recipient => {
<li><strong>Payment Plans:</strong> Choose from flexible payment plans that suit your budget and hiring needs.</li>
</ul>
<p>Ready to take your hiring to the next level? Sign up now via the link below and start reaching the talent you've been looking for!</p>
<p><a href="https://job-bank-mu.vercel.app/" style="background-color: #4CAF50; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;">Sign Up Now</a></p>
<p><a href=${process.env.NEXT_PUBLIC_JOB_BANK_API_URL} style="background-color: #4CAF50; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;">Sign Up Now</a></p>
<p>Don't miss out on the opportunity to find your next great hire effortlessly. Join us today and experience the power of our job panel!</p>
<p>Best regards,</p>
<p>The [Job Panel] Team</p>`,
Expand Down
77 changes: 77 additions & 0 deletions e2e/api.jest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { request, APIRequestContext } from '@playwright/test';
import { config } from './config';

const baseURL = `${config.BASE_URL}/api/job-posting`;

// Function to validate job properties
const validateJobProperties = (job: any) => {
expect(job).toHaveProperty('_id');
// Uncomment the properties you want to validate
// expect(job).toHaveProperty('jobTitle');
// expect(job).toHaveProperty('datePosted');
// expect(job).toHaveProperty('hiringOrganization');
// expect(job).toHaveProperty('streetAddress');
// expect(job).toHaveProperty('addressLocality');
// expect(job).toHaveProperty('addressRegion');
// expect(job).toHaveProperty('minCompValue');
// expect(job).toHaveProperty('maxCompValue');
// expect(job).toHaveProperty('compTimeUnit');
// expect(job).toHaveProperty('workHours');
// expect(job).toHaveProperty('specialCommitments');
// expect(job).toHaveProperty('email');
// expect(job).toHaveProperty('jobPageId');
// expect(job).toHaveProperty('employmentType');
// expect(job).toHaveProperty('employmentSubType');
// expect(job).toHaveProperty('startTime');
// expect(job).toHaveProperty('benefits');
// expect(job).toHaveProperty('vacancies');
// expect(job).toHaveProperty('verified');
// expect(job).toHaveProperty('validThrough');
// expect(job).toHaveProperty('description');
// expect(job).toHaveProperty('site1');
// expect(job).toHaveProperty('site2');
// expect(job).toHaveProperty('site3');
// expect(job).toHaveProperty('site4');
// expect(job).toHaveProperty('__v');
// expect(job).toHaveProperty('sent');
};

// Function to test the endpoints
const testEndpoint = async (context: APIRequestContext, endpoint: string) => {
const response = await context.get(`${baseURL}/${endpoint}?page_num=1`);
expect(response.status()).toBe(200);
const data = await response.json();

for (const joblist in data) {
for (const job of data[joblist]) {
validateJobProperties(job);
}
expect(data[joblist].length).toBeGreaterThan(0);
}
};

describe('API Job Postings', () => {
let context: APIRequestContext;

beforeAll(async () => {
context = await request.newContext();
});

afterAll(async () => {
await context.dispose();
});

const endpoints = [
// 'newcomers',
// 'disabled',
// 'indigenous',
// 'students',
'asylum-refugees',
];

endpoints.forEach(endpoint => {
it(`API: ${endpoint.charAt(0).toUpperCase() + endpoint.slice(1)} Postings`, async () => {
await testEndpoint(context, endpoint);
});
});
});
76 changes: 76 additions & 0 deletions e2e/api_date_sort.jest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { request, APIRequestContext } from '@playwright/test';
import { config } from './config';

const baseURL = `${config.BASE_URL}/api/job-posting`;

// Function to validate job properties
const validateJobProperties = (job: any) => {
expect(job).toHaveProperty('_id');
// Add other properties if needed
};

// Function to test the endpoints
const testEndpoint = async (
context: APIRequestContext,
endpoint: string,
sortOrder: string
) => {
const response = await context.get(
`${baseURL}/${endpoint}?sort=${sortOrder}&page_num=1`
);
expect(response.status()).toBe(200);

let data;
try {
data = await response.json();
} catch (error) {
throw new Error(
`Error parsing JSON response for ${endpoint} with sort ${sortOrder}: ${error}`
);
}

if (typeof data !== 'object' || Array.isArray(data)) {
throw new Error(
`Unexpected response format for ${endpoint} with sort ${sortOrder}`
);
}
for (const joblist in data) {
for (const job of data[joblist]) {
validateJobProperties(job);
}
expect(data[joblist].length).toBeGreaterThan(0);
}
};

describe('API Job Postings', () => {
let context: APIRequestContext;

beforeAll(async () => {
context = await request.newContext();
});

afterAll(async () => {
await context.dispose();
});

const endpoints = [
// 'newcomers',
// 'disabled',
// 'indigenous',
// 'students',
'asylum-refugees',
];

const sortOrders = [
'a', // ascending
'd', // descending
];

endpoints.forEach(endpoint => {
sortOrders.forEach(sortOrder => {
test(`API: ${endpoint.charAt(0).toUpperCase() + endpoint.slice(1)} Postings sorted ${sortOrder === 'a' ? 'ascending' : 'descending'}`, async () => {
await testEndpoint(context, endpoint, sortOrder);
});
});
});
});
Loading

0 comments on commit 228b95d

Please sign in to comment.