Skip to content

Commit

Permalink
feat: adds unit tests and use pathe whenever possible (#30)
Browse files Browse the repository at this point in the history
Co-authored-by: Florian Lefebvre <[email protected]>
  • Loading branch information
jdtjenkins and florian-lefebvre authored Jan 31, 2024
1 parent 214dc1d commit 08e73d9
Show file tree
Hide file tree
Showing 21 changed files with 1,230 additions and 57 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-rockets-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"astro-integration-kit": patch
---

Updates imports from `node:path` to `pathe`
25 changes: 25 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Tests

on: [pull_request]

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Setup PNPM
run: corepack enable && pnpm -v

- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 18.19.0
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Test
run: pnpm test
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
dist
dist
.TMP_*
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"changeset": "changeset",
"release": "node scripts/release.mjs",
"lint": "biome check .",
"lint:fix": "biome check --apply ."
"lint:fix": "biome check --apply .",
"test": "pnpm --filter astro-integration-kit test"
},
"devDependencies": {
"@biomejs/biome": "1.5.2",
Expand Down
8 changes: 8 additions & 0 deletions package/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ Start the playground:
pnpm playground:dev
```

Testing is using Vitest and all tests are co-located with the module they are testing.

To run all the tests:

```bash
pnpm test
```

You can now edit files in `package`. Please note that making changes to those files may require restarting the playground dev server.

## Licensing
Expand Down
5 changes: 3 additions & 2 deletions package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
".": "./src/index.ts"
},
"scripts": {
"build": "tsc && vite build"
"test": "vitest"
},
"type": "module",
"peerDependencies": {
Expand All @@ -32,7 +32,8 @@
"devDependencies": {
"@types/node": "^20.11.0",
"typescript": "^5.3.3",
"vite": "^5.0.11"
"vite": "^5.0.11",
"vitest": "^1.2.1"
},
"dependencies": {
"defu": "^6.1.4",
Expand Down
11 changes: 6 additions & 5 deletions package/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,12 @@ export interface ExtendedHooks {
* hasIntegration("@astrojs/tailwind")
* ```
*/
hasIntegration: (...params: (
| [name: string]
| [name: string, position: "before" | "after"]
| [name: string, position: "before" | "after", relativeTo: string]
)) => boolean;
hasIntegration: (
...params:
| [name: string]
| [name: string, position: "before" | "after"]
| [name: string, position: "before" | "after", relativeTo: string]
) => boolean;
/**
* In development, will reload the Astro dev server if any files within
* the integration directory has changed.
Expand Down
2 changes: 1 addition & 1 deletion package/src/utils/add-dts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { readFileSync, mkdirSync, writeFileSync } from "node:fs";
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, relative } from "node:path";
import { fileURLToPath } from "node:url";
import type { AstroIntegrationLogger } from "astro";
Expand Down
10 changes: 7 additions & 3 deletions package/src/utils/define-integration.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { AstroIntegration } from "astro";
import { defu } from "defu";
import type { ExtendedHooks } from "../types.js";
import { addVirtualImport } from "../utils/add-virtual-import.js";
import { addVitePlugin } from "../utils/add-vite-plugin.js";
import { addDts } from "./add-dts.js";
import { addVirtualImport } from "./add-virtual-import.js";
import { addVitePlugin } from "./add-vite-plugin.js";
import { hasIntegration } from "./has-integration.js";
import { watchIntegration } from "./watch-integration.js";

Expand Down Expand Up @@ -69,7 +69,11 @@ export const defineIntegration = <
}),
addVitePlugin: (plugin) =>
addVitePlugin({ plugin, updateConfig: params.updateConfig }),
hasIntegration: (_name: string, position?: "before" | "after", relativeTo?: string) =>
hasIntegration: (
_name: string,
position?: "before" | "after",
relativeTo?: string,
) =>
hasIntegration({
name: _name,
// When `relativeTo` is not set get positions relative the current integration.
Expand Down
39 changes: 22 additions & 17 deletions package/src/utils/has-integration.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import type { HookParameters } from "astro";
import { AstroError } from "astro/errors";

type HasIntegrationParams =
& (
| { position?: undefined, relativeTo?: string }
| { position: "before" | "after", relativeTo: string }
)
& {
name: string;
config: HookParameters<"astro:config:setup">["config"];
}
type HasIntegrationParams = (
| { position?: undefined; relativeTo?: string }
| { position: "before" | "after"; relativeTo: string }
) & {
name: string;
config: HookParameters<"astro:config:setup">["config"];
};

/**
* Checks whether an integration is already installed.
Expand Down Expand Up @@ -43,25 +41,32 @@ export const hasIntegration = ({
relativeTo,
config,
}: HasIntegrationParams): boolean => {
const integrationPosition = config.integrations.findIndex((integration) => integration.name === name);
const integrationPosition = config.integrations.findIndex(
(integration) => integration.name === name,
);

// Integration is not installed
if (integrationPosition === -1) return false;

// Not a relative check, the integration is present.
if (position === undefined) return true;

if (relativeTo === undefined) throw new AstroError(
'Cannot perform a relative integration check without a relative reference.',
'Pass `relativeTo` on your call to `hasIntegration` or remove the `position` option.',
);
if (relativeTo === undefined)
throw new AstroError(
"Cannot perform a relative integration check without a relative reference.",
"Pass `relativeTo` on your call to `hasIntegration` or remove the `position` option.",
);

const otherPosition = config.integrations.findIndex((integration) => integration.name === relativeTo);
const otherPosition = config.integrations.findIndex(
(integration) => integration.name === relativeTo,
);

if (otherPosition === -1) throw new AstroError('Cannot check relative position against an absent integration.');
if (otherPosition === -1)
throw new AstroError(
"Cannot check relative position against an absent integration.",
);

return position === "before"
? integrationPosition < otherPosition
: integrationPosition > otherPosition;
};

2 changes: 1 addition & 1 deletion package/src/utils/watch-integration.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { readdirSync, statSync } from "node:fs";
import { join, relative, resolve } from "node:path";
import type { HookParameters } from "astro";
import { join, relative, resolve } from "pathe";

const getFilesRecursively = (dir: string, baseDir = dir) => {
const files = readdirSync(dir);
Expand Down
140 changes: 140 additions & 0 deletions package/tests/unit/add-dts.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
import { fileURLToPath } from "url";
import type { AstroIntegrationLogger } from "astro";
import { dirname } from "pathe";
import { afterAll, beforeAll, describe, expect, test, vi } from "vitest";
import { addDts } from "../../src/utils/add-dts.js";
import { createResolver } from "../../src/utils/create-resolver.js";

const tempFolderName = ".TMP_ADDDTS/";
const { resolve } = createResolver(import.meta.url);
const { resolve: tempFolderResolver } = createResolver(resolve(tempFolderName));
const envDtsPath = resolve(`${tempFolderName}/env.d.ts`);

const createTempFiles = () => {
mkdirSync(resolve(tempFolderName));

writeFileSync(envDtsPath, `/// <reference types="astro/client" />`, {
encoding: "utf-8",
});
};

const deleteTempFiles = () => {
rmSync(resolve(tempFolderName), {
recursive: true,
force: true,
});
};

describe("addDts", () => {
beforeAll(() => {
createTempFiles();
});

afterAll(() => {
deleteTempFiles();
});

test("Should run", () => {
const dtsFileName = "TEST";
const dtsFileContent = 'declare module "my-integration" {}';
const root = new URL(tempFolderName, import.meta.url);
const srcDir = new URL(tempFolderName, import.meta.url);
const logger = {
info: vi.fn(),
} as unknown as AstroIntegrationLogger;

expect(() =>
addDts({
name: dtsFileName,
content: dtsFileContent,
logger,
root,
srcDir,
}),
).not.toThrow();
});

test("Should update the env.d.ts (double quotes)", () => {
const dtsFileName = "TEST";
const dtsFileContent = 'declare module "my-integration" {}';
const root = new URL(tempFolderName, import.meta.url);
const srcDir = new URL(tempFolderName, import.meta.url);
const logger = {
info: vi.fn(),
} as unknown as AstroIntegrationLogger;

const expectedEnvDtsContent = `/// <reference types="astro/client" />\n/// <reference types=".astro/${dtsFileName}.d.ts" />`;

addDts({
name: dtsFileName,
content: dtsFileContent,
logger,
root,
srcDir,
});

const fileContents = readFileSync(envDtsPath, {
encoding: "utf-8",
});

expect(fileContents).toEqual(expectedEnvDtsContent);
});

test("Should update the env.d.ts (single quotes)", () => {
const dtsFileName = "TEST";
const dtsFileContent = 'declare module "my-integration" {}';
const root = new URL(tempFolderName, import.meta.url);
const srcDir = new URL(tempFolderName, import.meta.url);
const logger = {
info: vi.fn(),
} as unknown as AstroIntegrationLogger;

const expectedEnvDtsContent = `/// <reference types='astro/client' />\n/// <reference types='.astro/${dtsFileName}.d.ts' />`;

writeFileSync(envDtsPath, `/// <reference types='astro/client' />`, {
encoding: "utf-8",
});

addDts({
name: dtsFileName,
content: dtsFileContent,
logger,
root,
srcDir,
});

const fileContents = readFileSync(envDtsPath, {
encoding: "utf-8",
});

expect(fileContents).toEqual(expectedEnvDtsContent);
});

test("Should create the virtual file", () => {
const dtsFileName = "TEST";
const dtsFileContent = 'declare module "my-integration" {}';
const root = new URL(tempFolderName, import.meta.url);
const srcDir = new URL(tempFolderName, import.meta.url);
const logger = {
info: vi.fn(),
} as unknown as AstroIntegrationLogger;

addDts({
name: dtsFileName,
content: dtsFileContent,
logger,
root,
srcDir,
});

const fileContents = readFileSync(
tempFolderResolver(`.astro/${dtsFileName}.d.ts`),
{
encoding: "utf-8",
},
);

expect(fileContents).toEqual(dtsFileContent);
});
});
Loading

0 comments on commit 08e73d9

Please sign in to comment.