Skip to content

Commit

Permalink
Create TestCaseExecution
Browse files Browse the repository at this point in the history
  • Loading branch information
abdala committed Oct 4, 2024
1 parent f7d187b commit 2ecbb63
Show file tree
Hide file tree
Showing 26 changed files with 220 additions and 135 deletions.
1 change: 1 addition & 0 deletions assert/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"scripts": {
"build": "rm -rf dist && tsc",
"test": "tsx --test test/*.test.ts",
"test:only": "tsx --test --test-only test/*.test.ts",
"test:coverage": "tsx --experimental-test-coverage --test test/*.test.ts"
}
}
1 change: 1 addition & 0 deletions dtc-aws-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"scripts": {
"build": "rm -rf dist && tsc",
"test": "AWS_MAX_ATTEMPTS=0 AWS_REGION=eu-west-1 AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test tsx --test test/*.test.ts",
"test:only": "AWS_MAX_ATTEMPTS=0 AWS_REGION=eu-west-1 AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test tsx --test --test-only test/*.test.ts",
"test:coverage": "AWS_MAX_ATTEMPTS=0 AWS_REGION=eu-west-1 AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test tsx --experimental-test-coverage --test test/*.test.ts"
}
}
1 change: 1 addition & 0 deletions dtc-mysql-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"scripts": {
"build": "rm -rf dist && tsc",
"test": "tsx --test test/*.test.ts",
"test:only": "tsx --test --test-only test/*.test.ts",
"test:coverage": "tsx --experimental-test-coverage --test test/*.test.ts"
}
}
6 changes: 3 additions & 3 deletions dtc-mysql-plugin/test/mock-mysql.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ import invalidQueryTestCase from './fixtures/mock-invalid-query'
const __dirname = dirname(fileURLToPath(import.meta.url))

test('It mocks mysql calls', async () => {
await executeTestCase(mockTestCase.narrow, [new FunctionCallPlugin(`${__dirname}/fixtures`), new MysqlMockPlugin()])
await executeTestCase(mockTestCase.narrow, [new FunctionCallPlugin(), new MysqlMockPlugin()], `${__dirname}/fixtures/mock.ts`)
})

test('It supports more than one mysql connection', async () => {
await executeTestCase(mockTwoConnectionsTestCase.narrow, [new FunctionCallPlugin(`${__dirname}/fixtures`), new MysqlMockPlugin()])
await executeTestCase(mockTwoConnectionsTestCase.narrow, [new FunctionCallPlugin(), new MysqlMockPlugin()], `${__dirname}/fixtures/mockTwoConnectionsTestCase.ts`)
})

test('It validates SQL queries', async () => {
try {
await executeTestCase(invalidQueryTestCase.narrow, [new FunctionCallPlugin(`${__dirname}/fixtures`), new MysqlMockPlugin()])
await executeTestCase(invalidQueryTestCase.narrow, [new FunctionCallPlugin(), new MysqlMockPlugin()], `${__dirname}/fixtures/invalidQueryTestCase.ts`)
} catch (e) {
if (e.code === 'ERR_ASSERTION' && e.operator === 'doesNotThrow') {
assert.ok(true)
Expand Down
1 change: 1 addition & 0 deletions dtc-playwright-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"scripts": {
"build": "rm -rf dist && tsc",
"test": "tsx --test test/*.test.ts",
"test:only": "tsx --test --test-only test/*.test.ts",
"test:coverage": "tsx --experimental-test-coverage --test test/*.test.ts"
}
}
11 changes: 7 additions & 4 deletions dtc-playwright-plugin/src/PlaywrightRunner.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import {Runner, TestCase, Plugins} from '@cgauge/dtc'
import {Runner, TestCaseExecution, Plugins} from '@cgauge/dtc'
import {spawnSync} from 'node:child_process'
import nodeAssert from 'node:assert'
import * as url from 'url'

const __dirname = url.fileURLToPath(new URL('.', import.meta.url))

export class PlaywrightRunner implements Runner {
constructor(private args: string[] = []) {}

async run(path: string, _testCase: TestCase[], _plugins: Plugins, type: string, config?: string) {
spawnSync(`npx playwright test ${this.args.join(' ')} ${__dirname}`, {
async run(testCaseExecutions: TestCaseExecution[], _plugins: Plugins, type: string, config?: string) {
const childProcess = spawnSync(`npx playwright test ${this.args.join(' ')} ${__dirname}`, {
stdio: 'inherit',
shell: true,
cwd: process.cwd(),
env: {
...process.env,
DTC_PLAYWRIGHT_FILE_PATH: path,
...(testCaseExecutions.length === 1 && {DTC_PLAYWRIGHT_PATH: testCaseExecutions[0].filePath}),
DTC_PLAYWRIGHT_TYPE: type,
DTC_PLAYWRIGHT_CONFIG: config,
},
})

nodeAssert.equal(childProcess.status, 0)
}
}
8 changes: 4 additions & 4 deletions dtc-playwright-plugin/src/browser.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {executeTestCase, resolveConfig} from '@cgauge/dtc'
import {test} from '@playwright/test'

const path = String(process.env.DTC_PLAYWRIGHT_FILE_PATH)
const path = process.env.DTC_PLAYWRIGHT_PATH
const type = String(process.env.DTC_PLAYWRIGHT_TYPE)
const config = String(process.env.DTC_PLAYWRIGHT_CONFIG)

const {testCases, plugins} = await resolveConfig(path, config)
const {testCaseExecutions, plugins} = await resolveConfig(path, config)

for (const testCase of testCases) {
test(testCase.name, async ({page}) => executeTestCase(testCase[type], plugins[type], {page}))
for (const {filePath, testCase} of testCaseExecutions) {
test(testCase.name, async ({page}) => executeTestCase(testCase[type], plugins[type], filePath, {page}))
}
11 changes: 7 additions & 4 deletions dtc-playwright-plugin/test/PlaywrightRunner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@ import assert from 'node:assert'
import {fileURLToPath} from 'url'
import {dirname} from 'path'
import {PlaywrightPlugin} from '../src/PlaywrightPlugin'
import testCase from './fixtures/base.js'
import testCase from './fixtures/t1.dtc.js'
import testCase2 from './fixtures/t2.dtc.js'

const __dirname = dirname(fileURLToPath(import.meta.url))

test('It calls playwright runner', async () => {
const playwrightRunner = new PlaywrightRunner()

await playwrightRunner.run(
`${__dirname}/fixtures/base.js`,
testCase,
[
{filePath: `${__dirname}/fixtures/t1.dtc.js`, testCase},
{filePath: `${__dirname}/fixtures/t2.dtc.js`, testCase: testCase2},
],
{playwright: [new PlaywrightPlugin()]},
'playwright',
`./dtc-playwright-plugin/test/fixtures/config.js`,
`./test/fixtures/config.js`,
)

assert.ok(true)
Expand Down
6 changes: 4 additions & 2 deletions dtc-playwright-plugin/test/fixtures/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {PlaywrightPlugin} from '../../src/PlaywrightPlugin.js'
export default {
runner: new PlaywrightRunner(),

plugins: (_basePath, _testCase) => ({
testRegex: /^(?!.*node_modules).*dtc-playwright-plugin\/.*\.dtc\.[jt]s?$/,

plugins: {
playwright: [new PlaywrightPlugin()],
})
},
}
File renamed without changes.
58 changes: 58 additions & 0 deletions dtc-playwright-plugin/test/fixtures/t2.dtc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {fileURLToPath} from 'url'
import {dirname} from 'path'

const __dirname = dirname(fileURLToPath(import.meta.url))

export default {
name: 'Test case 2',
playwright: {
arrange: {
url: `file://${__dirname}/login.html`,
actions: [
{
target: 'Username',
fill: '',
},
{
target: {
name: 'getByPlaceholder',
args: ['Your password'],
},
action: {
name: 'fill',
args: [''],
},
},
{
target: {
name: 'getByRole',
args: [
'button',
{
type: 'submit',
},
],
},
action: {
name: 'click',
},
},
{
target: "input#username[required]:invalid",
toBeVisible: true,
},
],
},
act: {
url: `file://${__dirname}/index.html`,
},
assert: {
playwright: [
{
target: "Index page",
toBeVisible: true,
},
],
},
},
}
1 change: 1 addition & 0 deletions dtc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"scripts": {
"build": "rm -rf dist && tsc && chmod +x ./dist/cli.js",
"test": "tsx --test test/*.test.ts",
"test:only": "tsx --test --test-only test/*.test.ts",
"test:single": "tsx --test",
"test:coverage": "tsx --experimental-test-coverage --test test/*.test.ts"
}
Expand Down
9 changes: 4 additions & 5 deletions dtc/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ const argv = cli({

const type = argv.flags.type
const config = argv.flags.config
const projectPath = process.cwd()
const fileNamePath = argv._[0] ?? null
const filePath = argv._[0] ?? null

const {testCases, plugins, runner} = await resolveConfig(fileNamePath, config)
const {testCaseExecutions, plugins, runner} = await resolveConfig(filePath, config)

for (const testCase of testCases) {
for (const {testCase} of testCaseExecutions) {
if (!(type in testCase)) {
throw new Error(`Invalid test type (${type})`)
}
Expand All @@ -42,4 +41,4 @@ if (!runner) {
throw new Error(`No test runner found`)
}

await runner.run(`${projectPath}/${fileNamePath}`, testCases, plugins, type, config)
await runner.run(testCaseExecutions, plugins, type, config)
84 changes: 41 additions & 43 deletions dtc/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,80 @@
import type {Runner, Plugins, TestCase} from './domain'
import {defaultPlugins, defaultTestRunner} from './index.js'
import type {Runner, Plugins, TestCase, TestCaseExecution} from './domain'
import {defaultLoader, defaultPlugins, defaultTestRunner} from './index.js'
import {readdirSync, statSync} from 'fs'
import {join} from 'path'

export type Config = {
plugins: Plugins
loader: (filePath: string) => TestCase
loader: (filePath: string) => Promise<TestCase>
runner: Runner
testDir: string
testRegex: string
}

export const resolveConfig = async (fileNamePath: string | null, config?: string) => {
export const resolveConfig = async (filePath?: string, configPath?: string) => {
const projectPath = process.cwd()
let runner: Runner = defaultTestRunner
let loader: ((filePath: string) => TestCase) | null = null
let testRegex = /.*\.dtc\.[jt]s?$/
let plugins = defaultPlugins
let loader = defaultLoader
let testRegex = /.*\.dtc\.[jt]s?$/

if (config) {
if (configPath) {
const {
plugins: customPlugins,
loader: customLoad,
runner: customTestRunner,
testRegex: customTestRegex,
} = (await import(`${process.cwd()}/${config}`)).default
} = await defaultLoader(`${process.cwd()}/${configPath}`)

runner = customTestRunner ?? defaultTestRunner
testRegex = customTestRegex ?? testRegex
loader = customLoad ?? loader
plugins = customPlugins ? customPlugins : defaultPlugins
testRegex = customTestRegex ?? testRegex
}

const testCases = await getTestCases(projectPath, fileNamePath, loader, testRegex)
return {testCases, plugins, runner}
const testCaseExecutions = await getTestCases(projectPath, loader, testRegex, filePath)

return {testCaseExecutions, plugins, runner}
}

const generateTestCaseExecution = async (filePath: string, loader: Config['loader']): Promise<TestCaseExecution> => ({
filePath,
testCase: await loader(filePath),
})

const getTestCases = async (
projectPath: string,
fileNamePath: string | null,
loader: ((filePath: string) => TestCase) | null,
loader: Config['loader'] | null,
testRegex: RegExp,
): Promise<TestCase[]> => {
if (fileNamePath) {
fileNamePath = `${projectPath}/${fileNamePath}`
const testCase = loader ? await loader(fileNamePath) : (await import(fileNamePath)).default

return [
{
...testCase,
fileName: fileNamePath,
},
]
filePath?: string,
): Promise<TestCaseExecution[]> => {
if (filePath) {
return loader
? [await generateTestCaseExecution(filePath, loader)]
: [await generateTestCaseExecution(filePath, defaultLoader)]
}

const files = loadTestFiles(projectPath, testRegex)
return await Promise.all(
files.map(async (file) => {
const testCase = loader ? await loader(file) : (await import(file)).default

return {
...testCase,
fileName: file,
}
}),
return await Promise.all(
files.map((file) =>
loader ? generateTestCaseExecution(file, loader) : generateTestCaseExecution(file, defaultLoader),
),
)
}

export const loadTestFiles = (dir: string, testRegex: RegExp, fileList: string[] = []): string[] => {
readdirSync(dir).forEach((file) => {
const filePath = join(dir, file)
export const loadTestFiles = (currentPath: string, testRegex: RegExp): string[] =>
readdirSync(currentPath)
.map((file) => {
const filePath = join(currentPath, file)

if (statSync(filePath).isDirectory()) {
loadTestFiles(filePath, testRegex, fileList)
} else if (testRegex.test(filePath)) {
fileList.push(filePath)
}
})
if (statSync(filePath).isDirectory()) {
return loadTestFiles(filePath, testRegex)
} else if (testRegex.test(filePath)) {
return filePath
}

return fileList
}
return null
})
.filter((item) => item !== null)
.flat()
Loading

0 comments on commit 2ecbb63

Please sign in to comment.