Skip to content

Commit cbb0e17

Browse files
committed
feat: add support for fixtures in cypress
* Bump Cypress to 7.1.0 * Bump MongoDB to 3.6.6 * Split helpers for unit testing to import only database helpers for Cypress
1 parent dd7dfa2 commit cbb0e17

File tree

11 files changed

+368
-252
lines changed

11 files changed

+368
-252
lines changed

.env.test

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
APP_DB_URI="mongodb://root:password@127.0.0.1:27017"
33
APP_DB_NAME="test"
44

5+
# smtp settings
6+
APP_SMTP_PORT=1025
7+
58
# session settings
69
APP_SESSION_SECRET=localSecret
710

@@ -11,4 +14,4 @@ APP_STORAGE_PORT=9000
1114
APP_STORAGE_SSL=false
1215
APP_STORAGE_ACCESS_KEY="AKIAIOSFODNN7EXAMPLE"
1316
APP_STORAGE_SECRET_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
14-
APP_STORAGE_BUKCET_TEST=app-test
17+
APP_STORAGE_BUCKET=app-test

cypress/plugins/index.ts

+33-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,42 @@
11
/// <reference types="cypress" />
2+
import fs from 'fs';
23
import path from 'path';
34
import loadEnvConfig from '../../devtools/env';
5+
import { cleanDatabase, setupDatabase, loadFixtures } from '../../src/__tests__/helpers/database';
6+
import PluginEvents = Cypress.PluginEvents;
7+
import PluginConfigOptions = Cypress.PluginConfigOptions;
8+
9+
const cypressDir = path.resolve(__dirname, '..');
10+
const fixtureDir = path.resolve(cypressDir, 'fixtures');
11+
const rootDir = path.resolve(cypressDir, '..');
412

513
/**
614
* @type {Cypress.PluginConfig}
715
*/
8-
module.exports = (on, config) => {
9-
const dir = path.resolve(__dirname, '../..');
16+
module.exports = (on: PluginEvents, config: PluginConfigOptions) => {
17+
// setup the environment
18+
loadEnvConfig(rootDir, true, true);
19+
20+
on('task', {
21+
async setupDatabase(fixtures = []) {
22+
await cleanDatabase();
23+
await setupDatabase();
24+
25+
if (fixtures.length) {
26+
const data = fixtures.map(name => {
27+
const fixturePath = path.resolve(fixtureDir, `${name}.json`);
28+
29+
if (!fs.existsSync(fixturePath)) {
30+
throw new Error(`Fixture "${name}" not found`);
31+
}
32+
33+
const raw = fs.readFileSync(fixturePath, 'utf8');
34+
35+
return JSON.parse(raw);
36+
});
1037

11-
loadEnvConfig(dir, true, true);
38+
await loadFixtures(data);
39+
}
40+
},
41+
});
1242
};

jest.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module.exports = {
66

77
testMatch: ['<rootDir>/src/**/__tests__/**/*.{js,ts,tsx}'],
88
testEnvironment: 'node',
9-
testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/src/__tests__/helpers.ts'],
9+
testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/src/__tests__/helpers/'],
1010

1111
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
1212

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
"@types/minio": "^7.0.7",
6969
"@types/mjml": "^4.7.0",
7070
"@types/mjml-react": "^1.0.6",
71-
"@types/mongodb": "^3.6.11",
71+
"@types/mongodb": "^3.6.12",
7272
"@types/node": "^14.14.34",
7373
"@types/node-fetch": "^2.5.8",
7474
"@types/nodemailer": "^6.4.1",
@@ -89,7 +89,7 @@
8989
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
9090
"copy-webpack-plugin": "^8.0.0",
9191
"css-loader": "^5.2.0",
92-
"cypress": "^6.6.0",
92+
"cypress": "^7.1.0",
9393
"dotenv": "^8.2.0",
9494
"dotenv-expand": "^5.1.0",
9595
"enquirer": "^2.3.6",
@@ -172,7 +172,7 @@
172172
"minio": "^7.0.18",
173173
"mjml": "^4.8.1",
174174
"mjml-react": "^1.2.0",
175-
"mongodb": "^3.6.4",
175+
"mongodb": "^3.6.6",
176176
"node-fetch": "^2.6.1",
177177
"nodemailer": "^6.5.0",
178178
"rate-limiter-flexible": "^2.2.1",

src/__tests__/helpers.ts

-199
This file was deleted.

src/__tests__/helpers/apollo.ts

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { createReadStream } from 'fs';
2+
import { ApolloClient, ApolloLink, from, InMemoryCache, NormalizedCacheObject } from '@apollo/client';
3+
import { createUploadLink } from 'apollo-upload-client';
4+
import Blob from 'fetch-blob';
5+
import FormData from 'form-data';
6+
import NodeFormData from 'formdata-node';
7+
import nodeFetch from 'node-fetch';
8+
9+
export type ApolloClientOptions = { authorizationToken?: string; language?: string };
10+
11+
export const getApolloClient = (uri: string, options?: ApolloClientOptions): ApolloClient<NormalizedCacheObject> => {
12+
const authLink = new ApolloLink((operation, forward) => {
13+
operation.setContext(({ headers }) => {
14+
const customHeaders = { ...headers };
15+
16+
if (options?.language) {
17+
customHeaders['Accept-Language'] = options?.language;
18+
}
19+
20+
if (options?.authorizationToken) {
21+
customHeaders.Authorization = `Bearer ${options?.authorizationToken}`;
22+
}
23+
24+
return {
25+
headers: customHeaders,
26+
};
27+
});
28+
29+
return forward(operation);
30+
});
31+
32+
const httpLink = createUploadLink({
33+
uri: `${uri}/graphql`,
34+
FormData: NodeFormData,
35+
fetch: async (url, options) => {
36+
const nextOptions = { ...options };
37+
38+
if (options?.body instanceof NodeFormData) {
39+
// formdata-node is not fully supported by node-fetch
40+
// at least on the v2.6.x (maybe on v3)
41+
// therefore we are going to copy the entries to form-data instead
42+
// we cannot directly use form-data for graphql-upload because it doesn't support node streams
43+
const formData = options?.body as NodeFormData;
44+
const nextFormData = new FormData();
45+
46+
// @ts-ignore
47+
for (const [field, value] of formData.entries()) {
48+
const blob = value?.__content;
49+
50+
if (blob instanceof Blob) {
51+
// @ts-ignore
52+
nextFormData.append(field, createReadStream(blob.__filePath));
53+
} else {
54+
nextFormData.append(field, value);
55+
}
56+
57+
nextOptions.body = nextFormData;
58+
}
59+
}
60+
61+
return nodeFetch(url, nextOptions);
62+
},
63+
});
64+
65+
return new ApolloClient({
66+
link: from([authLink, httpLink]),
67+
cache: new InMemoryCache(),
68+
});
69+
};

0 commit comments

Comments
 (0)