Skip to content

Commit ab51c7e

Browse files
committed
Fix tests
1 parent e52efdf commit ab51c7e

File tree

10 files changed

+171
-35
lines changed

10 files changed

+171
-35
lines changed

.env.sample

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DATOCMS_ACCOUNT_EMAIL=""
2+
DATOCMS_ACCOUNT_PASSWORD=""
3+
DATOCMS_ORGANIZATION_ID=""

.github/workflows/node.js.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,7 @@ jobs:
2626
- run: ./node_modules/.bin/lerna bootstrap
2727
- run: npm run build --if-present
2828
- run: npm test
29+
env:
30+
DATOCMS_ACCOUNT_EMAIL: ${{ secrets.DATOCMS_ACCOUNT_EMAIL }}
31+
DATOCMS_ACCOUNT_PASSWORD: ${{ secrets.DATOCMS_ACCOUNT_PASSWORD }}
32+
DATOCMS_ORGANIZATION_ID: ${{ secrets.DATOCMS_ORGANIZATION_ID }}

jest-helpers/generateNewCmaClient.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { buildClient, ClientConfigOptions } from '../packages/cma-client-node';
2-
31
import { fetch as ponyfillFetch } from '@whatwg-node/fetch';
2+
import { buildClient, ClientConfigOptions } from '../packages/cma-client-node';
43
import { generateNewDashboardClient } from './generateNewDashboardClient';
54

65
const fetchFn = typeof fetch === 'undefined' ? ponyfillFetch : fetch;
@@ -15,12 +14,16 @@ export async function generateNewCmaClient(
1514
) {
1615
const dashboardClient = await generateNewDashboardClient();
1716

17+
const randomString =
18+
Math.random().toString(36).substring(7) + new Date().getTime();
19+
1820
const site = await dashboardClient.sites.create({
19-
name: 'Project',
21+
name: `Project ${randomString}`,
2022
});
2123

2224
return buildClient({
2325
...extraConfig,
26+
// biome-ignore lint/style/noNonNullAssertion: We're owners of the site, so readwrite_token is present
2427
apiToken: site.readwrite_token!,
2528
...baseConfigOptions,
2629
});
Lines changed: 77 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
import { buildClient, ClientConfigOptions } from '../packages/dashboard-client';
2-
31
import { fetch as ponyfillFetch } from '@whatwg-node/fetch';
2+
import {
3+
ApiError,
4+
buildClient,
5+
Client,
6+
ClientConfigOptions,
7+
} from '../packages/dashboard-client';
48

59
const fetchFn = typeof fetch === 'undefined' ? ponyfillFetch : fetch;
610

@@ -9,27 +13,77 @@ export const baseConfigOptions: Partial<ClientConfigOptions> = {
913
fetchFn,
1014
};
1115

16+
function shuffleArray<T>(source: T[]) {
17+
const array = [...source];
18+
19+
for (let i = array.length - 1; i > 0; i--) {
20+
const j = Math.floor(Math.random() * (i + 1));
21+
const temp = array[i];
22+
array[i] = array[j];
23+
array[j] = temp;
24+
}
25+
return array;
26+
}
27+
1228
export async function generateNewDashboardClient(
1329
extraConfig?: Partial<ClientConfigOptions>,
14-
) {
15-
const randomString =
16-
Math.random().toString(36).substring(7) + new Date().getTime();
17-
18-
const client = buildClient({
19-
apiToken: null,
20-
...baseConfigOptions,
21-
});
22-
23-
const account = await client.account.create({
24-
email: `${randomString}@delete-this-at-midnight-utc.tk`,
25-
password: 'STRONG_pass123!',
26-
first_name: 'Test',
27-
company: 'DatoCMS',
28-
});
29-
30-
return buildClient({
31-
...extraConfig,
32-
apiToken: account.id,
33-
...baseConfigOptions,
34-
});
30+
): Promise<Client> {
31+
if (process.env.DATOCMS_SESSION_ID) {
32+
return buildClient({
33+
...extraConfig,
34+
apiToken: process.env.DATOCMS_SESSION_ID,
35+
organization: process.env.DATOCMS_ORGANIZATION_ID,
36+
...baseConfigOptions,
37+
});
38+
}
39+
40+
if (
41+
!process.env.DATOCMS_ACCOUNT_EMAIL ||
42+
!process.env.DATOCMS_ACCOUNT_PASSWORD
43+
) {
44+
throw new Error(
45+
'DATOCMS_ACCOUNT_EMAIL, DATOCMS_ACCOUNT_PASSWORD (and optionally DATOCMS_ORGANIZATION_ID) environment variables must be set on .env file!',
46+
);
47+
}
48+
49+
// To avoid incurring in rate limits, a pool of accouts that share the same
50+
// password and organization membership can be used.
51+
52+
const emails = shuffleArray(
53+
process.env.DATOCMS_ACCOUNT_EMAIL.split(/\s*,\s*/),
54+
);
55+
56+
for (const email of emails) {
57+
const client = buildClient({
58+
...extraConfig,
59+
apiToken: null,
60+
autoRetry: false,
61+
...baseConfigOptions,
62+
});
63+
64+
try {
65+
const account = await client.session.rawCreate({
66+
data: {
67+
type: 'email_credentials',
68+
attributes: {
69+
email: email,
70+
password: process.env.DATOCMS_ACCOUNT_PASSWORD,
71+
},
72+
},
73+
});
74+
75+
process.env.DATOCMS_SESSION_ID = account.data.id;
76+
77+
return generateNewDashboardClient(extraConfig);
78+
} catch (e) {
79+
// Let's try with next account
80+
if (e instanceof ApiError && e.findError('RATE_LIMIT_EXCEEDED')) {
81+
continue;
82+
}
83+
84+
throw e;
85+
}
86+
}
87+
88+
throw new Error('Account pool exhausted!');
3589
}

jest-helpers/globalSetup.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import 'dotenv/config';
2+
import { ApiError } from '../packages/dashboard-client';
3+
import { generateNewDashboardClient } from './generateNewDashboardClient';
4+
5+
function isOldEnough(isoDatetime: string) {
6+
const datetime = new Date(isoDatetime);
7+
8+
const oneDayAgo = new Date();
9+
oneDayAgo.setDate(oneDayAgo.getDate() - 1);
10+
11+
return datetime < oneDayAgo;
12+
}
13+
14+
export default async () => {
15+
const client = await generateNewDashboardClient();
16+
17+
// Context: multiple processes might be running tests in parallel (like in Github Actions)
18+
19+
const siteIds: string[] = [];
20+
21+
for await (const site of client.sites.listPagedIterator()) {
22+
// We don't want to destroy sites that might be used by other processes,
23+
// let's only delete old ones
24+
25+
// biome-ignore lint/style/noNonNullAssertion: Always present
26+
if (isOldEnough(site.created_at!)) {
27+
siteIds.push(site.id);
28+
}
29+
}
30+
31+
await Promise.all(
32+
siteIds.map(async (id) => {
33+
try {
34+
await client.sites.destroy(id);
35+
} catch (e) {
36+
if (e instanceof ApiError && e.findError('NOT_FOUND')) {
37+
// Other processes might have already deleted the project
38+
return;
39+
}
40+
41+
throw e;
42+
}
43+
}),
44+
);
45+
};

jest.config.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
module.exports = {
2-
preset: 'ts-jest',
3-
testEnvironment: 'node',
2+
preset: "ts-jest",
3+
testEnvironment: "node",
44
testTimeout: 60000,
5-
testMatch: ['**/*.test.ts'],
5+
testMatch: ["**/*.test.ts"],
66
transformIgnorePatterns: [
7-
'/packages/cma-client-node/node_modules/(?!(got|p-cancelable|@szmarczak|lowercase-keys)/)',
7+
"/packages/cma-client-node/node_modules/(?!(got|p-cancelable|@szmarczak|lowercase-keys)/)",
88
],
9+
setupFiles: ["dotenv/config"],
10+
globalSetup: "./jest-helpers/globalSetup.ts",
911
// collectCoverage: true,
1012
// collectCoverageFrom: [
1113
// 'packages/**/*.[jt]s?(x)',

package-lock.json

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
"rome": "^11.0.0",
3434
"ts-jest": "^29.1.1",
3535
"ts-node": "^10.7.0",
36-
"typescript": "^4.6.3"
36+
"typescript": "^4.6.3",
37+
"dotenv": "^16.4.1"
3738
},
3839
"homepage": "https://github.com/datocms/js-rest-api-clients",
3940
"repository": {

packages/cma-client-node/__tests__/publicInfo.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ describe('Public info', () => {
55
const client = await generateNewCmaClient();
66

77
const publicInfo = await client.publicInfo.find();
8-
expect(publicInfo.name).toEqual('Project');
8+
expect(publicInfo.name).toContain('Project');
99
});
1010
});

packages/cma-client-node/__tests__/site.test.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ describe('site', () => {
55
const client = await generateNewCmaClient();
66

77
const fetchedSite = await client.site.find();
8-
expect(fetchedSite.name).toEqual('Project');
8+
expect(fetchedSite.name).toContain('Project');
99

10-
const updatedSite = await client.site.update({ name: 'New project' });
11-
expect(updatedSite.name).toEqual('New project');
10+
const randomString =
11+
Math.random().toString(36).substring(7) + new Date().getTime();
12+
13+
const newName = `New project ${randomString}`;
14+
15+
const updatedSite = await client.site.update({ name: newName });
16+
expect(updatedSite.name).toEqual(newName);
1217
});
1318
});

0 commit comments

Comments
 (0)