From a29c4d58bdc8b6a73d4d5f07f92872be808cc148 Mon Sep 17 00:00:00 2001 From: Pierre Millot Date: Wed, 2 Feb 2022 17:04:57 +0100 Subject: [PATCH] chore: check if generated CTS match committed CTS (#107) --- .github/workflows/check.yml | 3 + tests/CTS/config.json | 10 +++ .../templates/java/requests.mustache | 0 .../templates/javascript/requests.mustache | 0 .../methods/requests/search.test.java} | 0 tests/package.json | 2 +- tests/src/client/generate.ts | 44 ++++-------- tests/src/methods/requests/generate.ts | 53 ++++----------- tests/src/methods/requests/templates.ts | 30 -------- tests/src/utils.ts | 68 +++++++++++++++---- 10 files changed, 96 insertions(+), 114 deletions(-) create mode 100644 tests/CTS/config.json rename tests/CTS/methods/{ => requests}/templates/java/requests.mustache (100%) rename tests/CTS/methods/{ => requests}/templates/javascript/requests.mustache (100%) rename tests/output/java/{tests/methods/requests/search.java => src/test/java/com/algolia/methods/requests/search.test.java} (100%) delete mode 100644 tests/src/methods/requests/templates.ts diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index be83b5fa1b..c3d71eceb3 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -158,5 +158,8 @@ jobs: - name: Generate CTS run: yarn cts:generate + - name: Check diff with pushed CTS + run: exit $(git status --porcelain ./tests/output | wc -l) + - name: Run CTS run: yarn cts:test diff --git a/tests/CTS/config.json b/tests/CTS/config.json new file mode 100644 index 0000000000..ab4c3e8081 --- /dev/null +++ b/tests/CTS/config.json @@ -0,0 +1,10 @@ +{ + "javascript": { + "extension": "test.ts", + "outputFolder": "tests" + }, + "java": { + "extension": "test.java", + "outputFolder": "src/test/java/com/algolia" + } +} diff --git a/tests/CTS/methods/templates/java/requests.mustache b/tests/CTS/methods/requests/templates/java/requests.mustache similarity index 100% rename from tests/CTS/methods/templates/java/requests.mustache rename to tests/CTS/methods/requests/templates/java/requests.mustache diff --git a/tests/CTS/methods/templates/javascript/requests.mustache b/tests/CTS/methods/requests/templates/javascript/requests.mustache similarity index 100% rename from tests/CTS/methods/templates/javascript/requests.mustache rename to tests/CTS/methods/requests/templates/javascript/requests.mustache diff --git a/tests/output/java/tests/methods/requests/search.java b/tests/output/java/src/test/java/com/algolia/methods/requests/search.test.java similarity index 100% rename from tests/output/java/tests/methods/requests/search.java rename to tests/output/java/src/test/java/com/algolia/methods/requests/search.test.java diff --git a/tests/package.json b/tests/package.json index 7db4140673..0b9f928967 100644 --- a/tests/package.json +++ b/tests/package.json @@ -6,7 +6,7 @@ ], "scripts": { "build": "tsc", - "generate": "yarn generate:methods:requets ${0:-javascript} ${1:-search} && yarn generate:client ${0:-javascript} ${1:-search} && yarn format ${0:-javascript}", + "generate": "yarn generate:methods:requets ${0:-javascript} ${1:-search} && yarn generate:client ${0:-javascript} ${1:-search}", "generate:methods:requets": "node dist/tests/src/methods/requests/main.js ${0:-javascript} ${1:-search}", "generate:client": "node dist/tests/src/client/main.js ${0:-javascript} ${1:-search}", "format": "../scripts/formatter.sh ${0:-javascript} tests/output/${0:-javascript} && yarn lint", diff --git a/tests/src/client/generate.ts b/tests/src/client/generate.ts index c5d05b18ff..744811868b 100644 --- a/tests/src/client/generate.ts +++ b/tests/src/client/generate.ts @@ -5,14 +5,18 @@ import Mustache from 'mustache'; import openapitools from '../../../openapitools.json'; import { walk, - extensionForLanguage, packageNames, createClientName, exists, + createOutputDir, + getOutputPath, + loadTemplates, } from '../utils'; import type { TestsBlock, Test, ModifiedStepForMustache } from './types'; +const testPath = 'client'; + async function loadTests(client: string): Promise { const testsBlocks: TestsBlock[] = []; const clientPath = `./CTS/client/${client}`; @@ -53,28 +57,6 @@ async function loadTests(client: string): Promise { return testsBlocks; } -async function loadTemplates( - language: string -): Promise> { - const templates: Record = {}; - const templatePath = `./CTS/client/templates/${language}`; - - await exists(`./CTS/client/templates/javascript`); - if (!(await exists(templatePath))) { - return {}; - } - - for await (const file of walk(templatePath)) { - if (!file.name.endsWith('.mustache')) { - continue; - } - const type = file.name.replace('.mustache', ''); - const fileContent = (await fsp.readFile(file.path)).toString(); - templates[type] = fileContent; - } - return templates; -} - export async function generateTests( language: string, client: string @@ -89,11 +71,12 @@ export async function generateTests( return; } - const outputPath = `output/${language}/tests/client/`; - await fsp.mkdir(outputPath, { recursive: true }); - const { suite: template, ...partialTemplates } = await loadTemplates( - language - ); + await createOutputDir({ language, testPath }); + + const { suite: template, ...partialTemplates } = await loadTemplates({ + language, + testPath, + }); if (!template) { // eslint-disable-next-line no-console @@ -117,10 +100,7 @@ export async function generateTests( }, partialTemplates ); - await fsp.writeFile( - `${outputPath}/${client}.${extensionForLanguage[language]}`, - code - ); + await fsp.writeFile(getOutputPath({ language, client, testPath }), code); } function serializeParameters(parameters: any): string { diff --git a/tests/src/methods/requests/generate.ts b/tests/src/methods/requests/generate.ts index 3070ba6f2d..916e091499 100644 --- a/tests/src/methods/requests/generate.ts +++ b/tests/src/methods/requests/generate.ts @@ -6,28 +6,27 @@ import openapitools from '../../../../openapitools.json'; import { createClientName, packageNames, - extensionForLanguage, - sourcePathForLanguage, capitalize, + getOutputPath, + createOutputDir, + loadTemplates, } from '../../utils'; import { loadCTS } from './cts'; -import { loadPartials, loadRequestsTemplate } from './templates'; -import type { CTSBlock } from './types'; -async function createOutputDir(language: string): Promise { - await fsp.mkdir(`output/${language}/${sourcePathForLanguage[language]}`, { - recursive: true, - }); -} +const testPath = 'methods/requests'; -async function generateRequestsTests( - cts: CTSBlock[], - template: string, +export async function generateTests( language: string, - client: string, - partials: Record + client: string ): Promise { + const { requests: template, ...partialTemplates } = await loadTemplates({ + language, + testPath, + }); + const cts = (await loadCTS(client)).requests; + await createOutputDir({ language, testPath }); + if (cts.length === 0) { return; } @@ -54,30 +53,8 @@ async function generateRequestsTests( }; }, }, - partials + partialTemplates ); - await fsp.writeFile( - `output/${language}/${sourcePathForLanguage[language]}/${client}.${extensionForLanguage[language]}`, - code - ); -} - -export async function generateTests( - language: string, - client: string -): Promise { - const template = await loadRequestsTemplate(language); - const cts = await loadCTS(client); - const partials = await loadPartials(language); - - await createOutputDir(language); - - await generateRequestsTests( - cts.requests, - template, - language, - client, - partials - ); + await fsp.writeFile(getOutputPath({ language, client, testPath }), code); } diff --git a/tests/src/methods/requests/templates.ts b/tests/src/methods/requests/templates.ts deleted file mode 100644 index ced1638aee..0000000000 --- a/tests/src/methods/requests/templates.ts +++ /dev/null @@ -1,30 +0,0 @@ -import fsp from 'fs/promises'; - -const partials = ['generateParams']; - -export async function loadPartials( - language: string -): Promise> { - const partialsObj = {}; - for (const partial of partials) { - try { - partialsObj[partial] = ( - await fsp.readFile( - `CTS/methods/templates/${language}/${partial}.mustache` - ) - ).toString(); - } catch (err) { - // ignore file not found - if ((err as any).code !== 'ENOENT') { - throw err; - } - } - } - return partialsObj; -} - -export async function loadRequestsTemplate(language: string): Promise { - return ( - await fsp.readFile(`CTS/methods/templates/${language}/requests.mustache`) - ).toString(); -} diff --git a/tests/src/utils.ts b/tests/src/utils.ts index 816eca112c..17d74dacf3 100644 --- a/tests/src/utils.ts +++ b/tests/src/utils.ts @@ -2,6 +2,7 @@ import fsp from 'fs/promises'; import path from 'path'; import openapitools from '../../openapitools.json'; +import ctsConfig from '../CTS/config.json'; // For each generator, we map the packageName with the language and client export const packageNames: Record< @@ -90,19 +91,8 @@ export function removeEnumType(obj: any): any { return obj; } -// All those language dependents object should be defined in the CTS itself -export const extensionForLanguage: Record = { - javascript: 'test.ts', - java: 'test.java', -}; - -export const sourcePathForLanguage: Record = { - javascript: 'tests/methods/requests', - java: 'src/test/java/com/algolia', -}; - -/* eslint-disable no-console */ function printUsage(commandName: string): void { + /* eslint-disable no-console */ console.log(`usage: ${commandName} language client`); // eslint-disable-next-line no-process-exit process.exit(1); @@ -130,10 +120,62 @@ export function parseCLI( // eslint-disable-next-line no-process-exit process.exit(1); } + /* eslint-enable no-console */ return { lang, client, }; } -/* eslint-enable no-console */ + +export async function createOutputDir({ + language, + testPath, +}: { + language: string; + testPath: string; +}): Promise { + await fsp.mkdir( + `output/${language}/${ctsConfig[language].outputFolder}/${testPath}`, + { + recursive: true, + } + ); +} + +export function getOutputPath({ + language, + client, + testPath, +}: { + language: string; + client: string; + testPath: string; +}): string { + return `output/${language}/${ctsConfig[language].outputFolder}/${testPath}/${client}.${ctsConfig[language].extension}`; +} + +export async function loadTemplates({ + language, + testPath, +}: { + language: string; + testPath: string; +}): Promise> { + const templates: Record = {}; + const templatePath = `./CTS/${testPath}/templates/${language}`; + + if (!(await exists(templatePath))) { + return {}; + } + + for await (const file of walk(templatePath)) { + if (!file.name.endsWith('.mustache')) { + continue; + } + const name = file.name.replace('.mustache', ''); + const fileContent = (await fsp.readFile(file.path)).toString(); + templates[name] = fileContent; + } + return templates; +}