Skip to content

Commit

Permalink
Merge pull request #31 from saasquatch/component-scope-fix
Browse files Browse the repository at this point in the history
Fix component scope in bundles
  • Loading branch information
Locrian24 authored Nov 1, 2023
2 parents 2f40042 + 9a9628a commit 98df4f9
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 64 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ jobs:
- name: Install deps and build (with cache)
uses: bahmutov/npm-install@v1

- name: Test (vitest)
run: npm run test:code

- name: Build
run: npm run build

- name: Test (vitest)
run: npm run test:code

- name: Size Test
run: npm run test:size
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [2.0.2] - 2023-11-01

### Fixed

- Changed bundling to support splits in common JS. Fixes #29

## [2.0.1] - 2023-09-21

### Changed
Expand Down Expand Up @@ -88,7 +94,8 @@ Initial release of `jotai-molecules`
- `createScope` for creating a scope for molecules
- `ScopeProvider` a React component for providing scope to the tree

[unreleased]: https://github.com/saasquatch/jotai-molecules/compare/v2.0.1...HEAD
[unreleased]: https://github.com/saasquatch/jotai-molecules/compare/v2.0.2...HEAD
[2.0.2]: https://github.com/saasquatch/jotai-molecules/releases/tag/v2.0.2
[2.0.1]: https://github.com/saasquatch/jotai-molecules/releases/tag/v2.0.1
[2.0.0]: https://github.com/saasquatch/jotai-molecules/releases/tag/v2.0.0
[1.1.1]: https://github.com/saasquatch/jotai-molecules/releases/tag/v1.1.1
Expand Down
3 changes: 1 addition & 2 deletions examples/old-typescript/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "bunshi",
"description": "A tiny, fast, dependency-free 1.18kb library for creating jotai atoms in a way that lets you lift state up, or push state down.",
"version": "2.0.1",
"version": "2.0.2",
"license": "MIT",
"author": "ReferralSaaSquatch.com, Inc.",
"homepage": "https://bunshi.org",
Expand Down
65 changes: 65 additions & 0 deletions src/bundle.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { ComponentScope as VanillaComponentScope } from "../dist/vanilla.js";
import { ComponentScope as VanillaComponentScopeMjs } from "../dist/vanilla.mjs";

import { ComponentScope as ReactComponentScope } from "../dist/react.js";
import { ComponentScope as ReactComponentScopeMjs } from "../dist/react.mjs";

import { ComponentScope as VueComponentScope } from "../dist/vue.js";
import { ComponentScope as VueComponentScopeMjs } from "../dist/vue.mjs";

import { createScope as VanillaCreateScope } from "../dist/vanilla.js";
import { createScope as VanillaCreateScopeMjs } from "../dist/vanilla.mjs";

import { createScope as ReactCreateScope } from "../dist/react.js";
import { createScope as ReactCreateScopeMjs } from "../dist/react.mjs";

import { createScope as VueCreateScope } from "../dist/vue.js";
import { createScope as VueCreateScopeMjs } from "../dist/vue.mjs";

import { molecule as VanillaMolecule } from "../dist/vanilla.js";
import { molecule as VanillaMoleculeMjs } from "../dist/vanilla.mjs";

import { molecule as ReactMolecule } from "../dist/react.js";
import { molecule as ReactMoleculeMjs } from "../dist/react.mjs";

import { molecule as VueMolecule } from "../dist/vue.js";
import { molecule as VueMoleculeMjs } from "../dist/vue.mjs";

/**
*
* LANDMINE: This requires build to have run first!!
*
*/
describe("Build artifacts", () => {
describe("Vue bundle", () => {
test("Exports are the same in CommonJS", () => {
expect(VueMolecule).toBe(VanillaMolecule);
expect(VueCreateScope).toBe(VanillaCreateScope);
// Test of the fix for https://github.com/saasquatch/bunshi/issues/29
expect(VueComponentScope).toBe(VanillaComponentScope);
});

test("Exports are the same in MJS", () => {
expect(VueMoleculeMjs).toBe(VanillaMoleculeMjs);
expect(VueCreateScopeMjs).toBe(VanillaCreateScopeMjs);
// Test of the fix for https://github.com/saasquatch/bunshi/issues/29
expect(VueComponentScopeMjs).toBe(VanillaComponentScopeMjs);
});
});

describe("React bundle", () => {
test("Exports are the same in CommonJS for React", () => {
expect(ReactMolecule).toBe(VanillaMolecule);
expect(ReactCreateScope).toBe(VanillaCreateScope);
// Test of the fix for https://github.com/saasquatch/bunshi/issues/29
expect(ReactComponentScope).toBe(VanillaComponentScope);
});

test("Exports are the same in MJS", () => {
expect(ReactMoleculeMjs).toBe(VanillaMoleculeMjs);
expect(ReactCreateScopeMjs).toBe(VanillaCreateScopeMjs);
// Test of the fix for https://github.com/saasquatch/bunshi/issues/29
expect(ReactComponentScopeMjs).toBe(VanillaComponentScopeMjs);
});
});
});
147 changes: 93 additions & 54 deletions src/react/ComponentScope.test.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,116 @@
import { act, renderHook } from '@testing-library/react-hooks';
import { act, renderHook } from "@testing-library/react-hooks";
import { atom, useAtom } from "jotai";
import { ComponentScope, molecule } from "./";
import { createTestInjectorProvider } from './internal/TestInjectorProvider';
import { createTestInjectorProvider } from "./internal/TestInjectorProvider";
import { useMolecule } from "./useMolecule";

const ComponentScopedCountMolecule = molecule((_, scope) => {
scope(ComponentScope);
return atom(0);
scope(ComponentScope);
return atom(0);
});

const GlobalScopedMoleculeCountMolecule = molecule((_, scope) => {
return atom(0);
return atom(0);
});

const useCounter = (mol: typeof ComponentScopedCountMolecule) => {
const [count, setCount] = useAtom(useMolecule(mol))
return {
count,
increment: () => setCount(c => c + 1)
}
const [count, setCount] = useAtom(useMolecule(mol));
return {
count,
increment: () => setCount((c) => c + 1),
};
};


describe("Global scoped molecules", () => {
test('should increment counter', () => {
testOneCounter(GlobalScopedMoleculeCountMolecule, 1);
})
test('two counters should be connected for global scope', () => {
// Note: This is an important test case, because
// it makes sure that our `testTwoCounters` function
// can tell the difference between a globally
// scoped molecule and not component-scope molecule
testTwoCounters(GlobalScopedMoleculeCountMolecule, 2);
})
})
test("should increment counter", () => {
testOneCounter(GlobalScopedMoleculeCountMolecule, 1);
});
test("two counters should be connected for global scope", () => {
// Note: This is an important test case, because
// it makes sure that our `testTwoCounters` function
// can tell the difference between a globally
// scoped molecule and not component-scope molecule
testTwoCounters(GlobalScopedMoleculeCountMolecule, {
actual1: true,
actual2: true,
expected1: 2,
expected2: 2,
});
});
});

describe("Component scoped molecules", () => {
test('should increment counter', () => {
testOneCounter(ComponentScopedCountMolecule, 1);
})
test('two counters should be not be connected when component scoped', () => {
testTwoCounters(ComponentScopedCountMolecule, 1);
})

})

function testOneCounter(mol: typeof ComponentScopedCountMolecule, expectedResult: number) {

const TestInjectorProvider = createTestInjectorProvider();

const { result } = renderHook(() => useCounter(mol), { wrapper: TestInjectorProvider });

act(() => {
result.current.increment();
test("should increment counter", () => {
testOneCounter(ComponentScopedCountMolecule, 1);
});
test("two counters should be not be connected when component scoped", () => {
testTwoCounters(ComponentScopedCountMolecule, {
actual1: true,
actual2: true,
expected1: 1,
expected2: 1,
});
});
test("two counters should be not be connected when component scoped, only one", () => {
testTwoCounters(ComponentScopedCountMolecule, {
actual1: true,
actual2: false,
expected1: 1,
expected2: 0,
});
});
test("two counters should be not be connected when component scoped, only one", () => {
testTwoCounters(ComponentScopedCountMolecule, {
actual1: false,
actual2: true,
expected1: 0,
expected2: 1,
});
});
});

expect(result.current.count).toBe(expectedResult);
}

function testTwoCounters(mol: typeof ComponentScopedCountMolecule, expectedResult: number) {
function testOneCounter(
mol: typeof ComponentScopedCountMolecule,
expectedResult: number
) {
const TestInjectorProvider = createTestInjectorProvider();

const TestInjectorProvider = createTestInjectorProvider();
const { result } = renderHook(() => useCounter(mol), {
wrapper: TestInjectorProvider,
});

const { result: result1 } = renderHook(() => useCounter(mol), { wrapper: TestInjectorProvider });
const { result: result2 } = renderHook(() => useCounter(mol), { wrapper: TestInjectorProvider });
act(() => {
result.current.increment();
});

act(() => {
result1.current.increment();
});
act(() => {
result2.current.increment();
});
expect(result.current.count).toBe(expectedResult);
}

expect(result1.current.count).toBe(expectedResult);
expect(result2.current.count).toBe(expectedResult);
function testTwoCounters(
mol: typeof ComponentScopedCountMolecule,
opts: {
actual1: boolean;
actual2: boolean;
expected2: number;
expected1: number;
}
) {
const TestInjectorProvider = createTestInjectorProvider();

const { result: result1 } = renderHook(() => useCounter(mol), {
wrapper: TestInjectorProvider,
});
const { result: result2 } = renderHook(() => useCounter(mol), {
wrapper: TestInjectorProvider,
});

act(() => {
opts.actual1 && result1.current.increment();
});
act(() => {
opts.actual2 && result2.current.increment();
});

expect(result1.current.count).toBe(opts.expected1);
expect(result2.current.count).toBe(opts.expected2);
}
3 changes: 2 additions & 1 deletion tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ export default defineConfig({
"cjs", "esm"
],
// Cleanup dist on builds
clean: true
clean: true,
splitting: true
})

0 comments on commit 98df4f9

Please sign in to comment.