Skip to content

Commit

Permalink
feat: add initial tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rellafella committed Feb 24, 2025
1 parent 577341b commit ff0d55b
Show file tree
Hide file tree
Showing 29 changed files with 1,123 additions and 1 deletion.
151 changes: 151 additions & 0 deletions test/cli.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import { execa } from 'execa';
import fse from 'fs-extra';
import path from 'node:path';
import process from 'node:process';
import { afterAll, beforeEach, describe, expect, it } from 'vitest';
import { version } from '../package.json';

describe('CLI basics', () => {
it('should print version', async () => {
const { exitCode, stdout } = await execa('envsa', ['--version'], {
localDir: process.cwd(),
preferLocal: true,
});

expect(exitCode).toMatchInlineSnapshot(`0`);
expect(stdout).toBe(version);
});

it('should print version with short flag', async () => {
const { exitCode, stdout } = await execa('envsa', ['-v'], {
localDir: process.cwd(),
preferLocal: true,
});

expect(exitCode).toMatchInlineSnapshot(`0`);
expect(stdout).toBe(version);
});

it('should print help', async () => {
const { exitCode, stdout } = await execa('envsa', ['--help'], {
localDir: process.cwd(),
preferLocal: true,
});

expect(exitCode).toMatchInlineSnapshot(`0`);
expect(stdout).toMatchInlineSnapshot(`
"envsa <command>
Run aggregated @envsa/shared-config commands.
Commands:
envsa <command> Run aggregated @envsa/shared-config commands. [default]
envsa init Initialize configuration files for the entire suite of @envsa/shared-config tools. Will use option flags where possible if provided, but some of the invoked tools will ignore them.
envsa lint [files..] Lint your project with multiple tools in one go. Will use file arguments / globs where possible if provided, but some of the invoked tools only operate at the package-scope.
envsa fix [files..] Fix your project with multiple tools in one go. Will use file arguments / globs where possible if provided, but some of the invoked tools only operate at the package-scope.
envsa print-config [file] Print aggregated tool configuration data. Will use file arguments / globs where possible if provided, but some of the invoked tools only operate at the package-scope.
Options:
-h, --help Show help [boolean]
-v, --version Show version number [boolean]"
`);
});

it('should print help with short flag', async () => {
const { exitCode, stdout } = await execa('envsa', ['-h'], {
localDir: process.cwd(),
preferLocal: true,
});

expect(exitCode).toMatchInlineSnapshot(`0`);
expect(stdout).toMatchInlineSnapshot(`
"envsa <command>
Run aggregated @envsa/shared-config commands.
Commands:
envsa <command> Run aggregated @envsa/shared-config commands. [default]
envsa init Initialize configuration files for the entire suite of @envsa/shared-config tools. Will use option flags where possible if provided, but some of the invoked tools will ignore them.
envsa lint [files..] Lint your project with multiple tools in one go. Will use file arguments / globs where possible if provided, but some of the invoked tools only operate at the package-scope.
envsa fix [files..] Fix your project with multiple tools in one go. Will use file arguments / globs where possible if provided, but some of the invoked tools only operate at the package-scope.
envsa print-config [file] Print aggregated tool configuration data. Will use file arguments / globs where possible if provided, but some of the invoked tools only operate at the package-scope.
Options:
-h, --help Show help [boolean]
-v, --version Show version number [boolean]"
`);
});
});

describe.skip('CLI rule configuration', () => {
const tempDirectory = './input-copy/';

beforeEach(async () => {
await fse.rm(tempDirectory, { force: true, recursive: true });
});

afterAll(async () => {
await fse.rm(tempDirectory, { force: true, recursive: true });
});

it('should not fix anything unless asked', { timeout: 60_000 }, async () => {
const sourceDirectory = './test/fixtures/input/';
await fse.copy(sourceDirectory, tempDirectory);

await execa('envsa', [], {
localDir: process.cwd(),
preferLocal: true,
reject: false,
});

for (const file of await fse.readdir(tempDirectory)) {
const fileContent = await fse.readFile(path.join(tempDirectory, file), 'utf8');
const originalContent = await fse.readFile(path.join(sourceDirectory, file), 'utf8');
expect(fileContent).toEqual(originalContent);
}
});

it('should fix auto-fixable things', { timeout: 60_000 }, async () => {
const sourceDirectory = './test/fixtures/input/';
const destinationDirectory = './test/fixtures/output-fixed-auto/';
await fse.copy(sourceDirectory, tempDirectory);

await execa('envsa', ['--fix'], {
localDir: process.cwd(),
preferLocal: true,
reject: false,
});

for (const file of await fse.readdir(tempDirectory)) {
const fileContent = await fse.readFile(path.join(tempDirectory, file), 'utf8');
const destinationFilePath = path.join('../', destinationDirectory, path.basename(file));

await fse.createFile(destinationFilePath);
await expect(fileContent).toMatchFileSnapshot(destinationFilePath);
}
});

it('should catch errors as expected', { timeout: 60_000 }, async () => {
const sourceDirectory = './test/fixtures/input/';
await fse.copy(sourceDirectory, tempDirectory);

const { exitCode, stdout } = await execa('envsa', [], {
// Disable color output
env: {
// Disable color output
// eslint-disable-next-line ts/naming-convention
NO_COLOR: '1',
},
localDir: process.cwd(),
preferLocal: true,
reject: false,
});

expect(exitCode).toMatchInlineSnapshot(`1`);
//
/* cspell:disable */
expect(stdout).toMatchInlineSnapshot(`""`);
//
/* cspell:enable */
});
});
56 changes: 56 additions & 0 deletions test/fixtures/input/Svelte.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<script lang="ts">
export const content = 'hi!';
</script>

<article>
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
<div>{@html content}</div>
</article>

<style lang="postcss">
/* Stylelint should work here */
button div {
position: relative;
box-shadow: -2px 3px 5px #00000067;
}
@media (hover: hover) {
button:not(:disabled):hover div:not(.down) {
color: white;
/* background-color: theme(colors.vm-magenta); */
background-color: #f01ef6;
/* text-shadow: 0 0 3px white; */
}
/* button:not(:hover) div { */
/* transition: 500ms; */
/* } */
}
button:not(:disabled):active div {
right: 2px;
top: 2px;
/* background-color: theme(colors.vm-magenta-mild); */
box-shadow: 0 1px 3px #00000067;
background-color: #c63bee;
}
button {
cursor: pointer;
user-select: none;
transition: opacity 500ms;
}
button div.down {
right: 2px;
top: 2px;
/* stylelint-disable-next-line function-no-unknown */
background-color: #ef1ef68f;
box-shadow: 0 1px 3px #00000067;
}
button:disabled {
opacity: 50%;
}
</style>
11 changes: 11 additions & 0 deletions test/fixtures/input/css.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@media (max-width: 480px) {
.bd-examples {
margin-right: -0.75rem;
margin-left: -0.75rem;
}

.bd-examples > [class^='col-'] {
padding-left: 0.75rem;
padding-right: 0.75rem;
}
}
28 changes: 28 additions & 0 deletions test/fixtures/input/html.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!doctype html>
<html class="no-js mY-ClAsS">
<head>
<meta charset="utf-8" />
<title>My tITlE</title>
<meta name="description" content="My CoNtEnT" />
<style>
/* Stylelint should work here */
@media (max-width: 480px) {
.bd-examples {
margin-right: -0.75rem;
margin-left: -0.75rem;
}

.bd-examples > [class^='col-'] {
padding-left: 0.75rem;
padding-right: 0.75rem;
}
}
</style>
</head>
<body>
<p>
Hello world!<br />
This is HTML5 Boilerplate.
</p>
</body>
</html>
66 changes: 66 additions & 0 deletions test/fixtures/input/javascript.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// This file is generated by ChatGPT

// eslint-disable-next-line no-console
var log = console.log;

// Define a class using ES6 class syntax
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

// Define a method within the class
sayHello() {
log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}

// Create an array of objects
const people = [new Person('Alice', 30), new Person('Bob', 25), new Person('Charlie', 35)];

// Use the forEach method to iterate over the array
people.forEach((person) => {
person.sayHello();
});

// Use a template literal to create a multiline string
const multilineString = `
This is a multiline string
that spans multiple lines.
`;

// Use destructuring assignment to extract values from an object
const { name, age } = people[0];
log(`First person in the array is ${name} and they are ${age} years old.`, multilineString);

// Use the spread operator to create a new array
const numbers = [1, 2, 3];
const newNumbers = [...numbers, 4, 5];
log(newNumbers);

// Use a try-catch block for error handling
try {
// Attempt to parse an invalid JSON string
JSON.parse('invalid JSON');
} catch (error) {
console.error('Error parsing JSON:', error.message);
}

// Use a ternary conditional operator
const isEven = (num) => num % 2 === 0;
const number = 7;
log(`${number} is ${isEven(number) ? 'even' : 'odd'}.`);

// Use a callback function with setTimeout for asynchronous code
setTimeout(() => {
log('This code runs after a delay of 2 seconds.');
}, 2000);

let a, b, c, d, foo;

if (a || b || c || d || (d && b)) {
foo();
}

export {};
35 changes: 35 additions & 0 deletions test/fixtures/input/markdown.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Header

_Look,_ code blocks are formatted _too!_

```js
// This should be handled by ESLint instead of Prettier
function identity(x) {
if (foo) {
console.log('bar');
}
}
```

```css
/* This should be handled by Prettier */
.foo {
color: red;
}
```

| Pilot | Airport | Hours |
| -------- | :-----: | ----: |
| John Doe | SKG | 1338 |
| Jane Roe | JFK | 314 |

---

- List
- with a [link] (/to/somewhere)
- and [another one]

[another one]: http://example.com 'Example title'

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Curabitur consectetur maximus risus, sed maximus tellus tincidunt et.
25 changes: 25 additions & 0 deletions test/fixtures/input/svg.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions test/fixtures/input/tsconfig.testonly.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"target": "ESNext",
"skipLibCheck": true,
"strict": true,
"skipDefaultLibCheck": true,
"module": "ESNext",
"moduleResolution": "Bundler"
}
}
Loading

0 comments on commit ff0d55b

Please sign in to comment.