@@ -6693,6 +6693,25 @@ tsconfig.json
6693
6693
26: }
6694
6694
````
6695
6695
6696
+ ## File: src/e2e/cypress/tsconfig.json
6697
+ ````json
6698
+ 1: {
6699
+ 2: "extends": "../../../tsconfig.json",
6700
+ 3: "compilerOptions": {
6701
+ 4: "noEmit": true,
6702
+ 5: "isolatedModules": false,
6703
+ 6: "types": ["cypress", "@testing-library/cypress"]
6704
+ 7: },
6705
+ 8: "include": [
6706
+ 9: "../../../node_modules/cypress",
6707
+ 10: "../../../node_modules/@testing-library/cypress",
6708
+ 11: "support/component.ts",
6709
+ 12: "support/component.d.ts",
6710
+ 13: "./**/*.ts"
6711
+ 14: ]
6712
+ 15: }
6713
+ ````
6714
+
6696
6715
## File: src/e2e/playwright/cv.spec.ts
6697
6716
````typescript
6698
6717
1: import { test, expect } from "@playwright/test";
@@ -9333,6 +9352,92 @@ tsconfig.json
9333
9352
303: export declare const internalGroqTypeReferenceTo: unique symbol;
9334
9353
````
9335
9354
9355
+ ## File: src/utils/eslint/index.ts
9356
+ ````typescript
9357
+ 1: import { ESLintUtils, TSESTree, TSESLint } from "@typescript-eslint/utils";
9358
+ 2: type MessageIds = "missingAAAPattern";
9359
+ 3: type Options = [];
9360
+ 4: const isTestFunction = (node: TSESTree.CallExpression): boolean => {
9361
+ 5: const testNames = ["it", "test"];
9362
+ 6: return (
9363
+ 7: node.callee.type === TSESTree.AST_NODE_TYPES.Identifier &&
9364
+ 8: testNames.includes(node.callee.name)
9365
+ 9: );
9366
+ 10: };
9367
+ 11: const isArrowFunction = (
9368
+ 12: node: TSESTree.Node,
9369
+ 13: ): node is TSESTree.ArrowFunctionExpression => {
9370
+ 14: return node?.type === TSESTree.AST_NODE_TYPES.ArrowFunctionExpression;
9371
+ 15: };
9372
+ 16: const validateAAAPattern = (
9373
+ 17: context: Readonly<TSESLint.RuleContext<MessageIds, Options>>,
9374
+ 18: node: TSESTree.CallExpression,
9375
+ 19: ) => {
9376
+ 20: const testFn = node.arguments[1];
9377
+ 21: if (!isArrowFunction(testFn)) return;
9378
+ 22: if (!hasAAAComments(context, testFn)) {
9379
+ 23: context.report({
9380
+ 24: node,
9381
+ 25: messageId: "missingAAAPattern",
9382
+ 26: });
9383
+ 27: }
9384
+ 28: };
9385
+ 29: const validateTestCase = (
9386
+ 30: context: Readonly<TSESLint.RuleContext<MessageIds, Options>>,
9387
+ 31: node: TSESTree.CallExpression,
9388
+ 32: ) => {
9389
+ 33: if (!isTestFunction(node)) return;
9390
+ 34: validateAAAPattern(context, node);
9391
+ 35: };
9392
+ 36: const hasAAAComments = (
9393
+ 37: context: Readonly<TSESLint.RuleContext<MessageIds, Options>>,
9394
+ 38: testFn: TSESTree.ArrowFunctionExpression,
9395
+ 39: ): boolean => {
9396
+ 40: const comments = context.getSourceCode().getCommentsInside(testFn.body);
9397
+ 41: const patterns = ["Arrange", "Act", "Assert"];
9398
+ 42: return comments.some((comment: TSESTree.Comment) =>
9399
+ 43: patterns.some((pattern) => comment.value.includes(pattern)),
9400
+ 44: );
9401
+ 45: };
9402
+ 46: const createRule = ESLintUtils.RuleCreator(
9403
+ 47: (name) =>
9404
+ 48: `https://github.com/your-repo/eslint-plugin/blob/main/docs/rules/${name}.md`,
9405
+ 49: );
9406
+ 50: const rule = createRule<Options, MessageIds>({
9407
+ 51: name: "arrange-act-assert",
9408
+ 52: meta: {
9409
+ 53: type: "suggestion",
9410
+ 54: docs: {
9411
+ 55: description: "enforce AAA pattern in tests",
9412
+ 56: },
9413
+ 57: messages: {
9414
+ 58: missingAAAPattern: "Test should follow AAA pattern with comments",
9415
+ 59: },
9416
+ 60: schema: [],
9417
+ 61: },
9418
+ 62: defaultOptions: [],
9419
+ 63: create(context) {
9420
+ 64: return {
9421
+ 65: CallExpression: (node: TSESTree.CallExpression) =>
9422
+ 66: validateTestCase(context, node),
9423
+ 67: };
9424
+ 68: },
9425
+ 69: });
9426
+ 70: module.exports = {
9427
+ 71: configs: {
9428
+ 72: recommended: {
9429
+ 73: plugins: ["test-rules"],
9430
+ 74: rules: {
9431
+ 75: "test-rules/arrange-act-assert": "error",
9432
+ 76: },
9433
+ 77: },
9434
+ 78: },
9435
+ 79: rules: {
9436
+ 80: "arrange-act-assert": rule,
9437
+ 81: },
9438
+ 82: };
9439
+ ````
9440
+
9336
9441
## File: src/utils/eslint/package.json
9337
9442
````json
9338
9443
1: {
@@ -15371,25 +15476,6 @@ tsconfig.json
15371
15476
78: export default ProsjektCard;
15372
15477
````
15373
15478
15374
- ## File: src/e2e/cypress/tsconfig.json
15375
- ````json
15376
- 1: {
15377
- 2: "extends": "../../../tsconfig.json",
15378
- 3: "compilerOptions": {
15379
- 4: "noEmit": true,
15380
- 5: "isolatedModules": false,
15381
- 6: "types": ["cypress", "@testing-library/cypress"]
15382
- 7: },
15383
- 8: "include": [
15384
- 9: "../../../node_modules/cypress",
15385
- 10: "../../../node_modules/@testing-library/cypress",
15386
- 11: "support/component.ts",
15387
- 12: "support/component.d.ts",
15388
- 13: "./**/*.ts"
15389
- 14: ]
15390
- 15: }
15391
- ````
15392
-
15393
15479
## File: src/stories/components/Index/MobileBackground.stories.tsx
15394
15480
````typescript
15395
15481
1: import React from "react";
@@ -15558,92 +15644,6 @@ tsconfig.json
15558
15644
39: export default KontaktWithMocks;
15559
15645
````
15560
15646
15561
- ## File: src/utils/eslint/index.ts
15562
- ````typescript
15563
- 1: import { ESLintUtils, TSESTree, TSESLint } from "@typescript-eslint/utils";
15564
- 2: type MessageIds = "missingAAAPattern";
15565
- 3: type Options = [];
15566
- 4: const isTestFunction = (node: TSESTree.CallExpression): boolean => {
15567
- 5: const testNames = ["it", "test"];
15568
- 6: return (
15569
- 7: node.callee.type === TSESTree.AST_NODE_TYPES.Identifier &&
15570
- 8: testNames.includes(node.callee.name)
15571
- 9: );
15572
- 10: };
15573
- 11: const isArrowFunction = (
15574
- 12: node: TSESTree.Node,
15575
- 13: ): node is TSESTree.ArrowFunctionExpression => {
15576
- 14: return node?.type === TSESTree.AST_NODE_TYPES.ArrowFunctionExpression;
15577
- 15: };
15578
- 16: const validateAAAPattern = (
15579
- 17: context: Readonly<TSESLint.RuleContext<MessageIds, Options>>,
15580
- 18: node: TSESTree.CallExpression,
15581
- 19: ) => {
15582
- 20: const testFn = node.arguments[1];
15583
- 21: if (!isArrowFunction(testFn)) return;
15584
- 22: if (!hasAAAComments(context, testFn)) {
15585
- 23: context.report({
15586
- 24: node,
15587
- 25: messageId: "missingAAAPattern",
15588
- 26: });
15589
- 27: }
15590
- 28: };
15591
- 29: const validateTestCase = (
15592
- 30: context: Readonly<TSESLint.RuleContext<MessageIds, Options>>,
15593
- 31: node: TSESTree.CallExpression,
15594
- 32: ) => {
15595
- 33: if (!isTestFunction(node)) return;
15596
- 34: validateAAAPattern(context, node);
15597
- 35: };
15598
- 36: const hasAAAComments = (
15599
- 37: context: Readonly<TSESLint.RuleContext<MessageIds, Options>>,
15600
- 38: testFn: TSESTree.ArrowFunctionExpression,
15601
- 39: ): boolean => {
15602
- 40: const comments = context.getSourceCode().getCommentsInside(testFn.body);
15603
- 41: const patterns = ["Arrange", "Act", "Assert"];
15604
- 42: return comments.some((comment: TSESTree.Comment) =>
15605
- 43: patterns.some((pattern) => comment.value.includes(pattern)),
15606
- 44: );
15607
- 45: };
15608
- 46: const createRule = ESLintUtils.RuleCreator(
15609
- 47: (name) =>
15610
- 48: `https://github.com/your-repo/eslint-plugin/blob/main/docs/rules/${name}.md`,
15611
- 49: );
15612
- 50: const rule = createRule<Options, MessageIds>({
15613
- 51: name: "arrange-act-assert",
15614
- 52: meta: {
15615
- 53: type: "suggestion",
15616
- 54: docs: {
15617
- 55: description: "enforce AAA pattern in tests",
15618
- 56: },
15619
- 57: messages: {
15620
- 58: missingAAAPattern: "Test should follow AAA pattern with comments",
15621
- 59: },
15622
- 60: schema: [],
15623
- 61: },
15624
- 62: defaultOptions: [],
15625
- 63: create(context) {
15626
- 64: return {
15627
- 65: CallExpression: (node: TSESTree.CallExpression) =>
15628
- 66: validateTestCase(context, node),
15629
- 67: };
15630
- 68: },
15631
- 69: });
15632
- 70: module.exports = {
15633
- 71: configs: {
15634
- 72: recommended: {
15635
- 73: plugins: ["test-rules"],
15636
- 74: rules: {
15637
- 75: "test-rules/arrange-act-assert": "error",
15638
- 76: },
15639
- 77: },
15640
- 78: },
15641
- 79: rules: {
15642
- 80: "arrange-act-assert": rule,
15643
- 81: },
15644
- 82: };
15645
- ````
15646
-
15647
15647
## File: studio/package.json
15648
15648
````json
15649
15649
1: {
@@ -16999,69 +16999,6 @@ tsconfig.json
16999
16999
19: });
17000
17000
````
17001
17001
17002
- ## File: src/types/testing-library.d.ts
17003
- ````typescript
17004
- 1: /// <reference types="jest" />
17005
- 2: /// <reference types="@testing-library/jest-dom" />
17006
- 3: // Extend Jest matchers - using module augmentation instead of namespace declaration
17007
- 4: declare global {
17008
- 5: namespace jest {
17009
- 6: interface Matchers<R> {
17010
- 7: toBeInTheDocument(): R;
17011
- 8: toHaveTextContent(text: string): R;
17012
- 9: toBeVisible(): R;
17013
- 10: toBeDisabled(): R;
17014
- 11: toBeEnabled(): R;
17015
- 12: toHaveAttribute(attr: string, value?: string): R;
17016
- 13: toHaveClass(className: string): R;
17017
- 14: toHaveStyle(css: React.CSSProperties): R;
17018
- 15: }
17019
- 16: }
17020
- 17: }
17021
- 18: // Augment Chai assertions for Cypress
17022
- 19: declare global {
17023
- 20: namespace Chai {
17024
- 21: interface Assertion {
17025
- 22: toBeInTheDocument(): Assertion;
17026
- 23: toHaveTextContent(text: string): Assertion;
17027
- 24: toBeVisible(): Assertion;
17028
- 25: toBeDisabled(): Assertion;
17029
- 26: toBeEnabled(): Assertion;
17030
- 27: toHaveAttribute(attr: string, value?: string): Assertion;
17031
- 28: toHaveClass(...classNames: string[]): Assertion;
17032
- 29: toHaveStyle(css: React.CSSProperties): Assertion;
17033
- 30: toHaveBeenCalled(): Assertion;
17034
- 31: toHaveBeenCalledWith(...args: unknown[]): Assertion;
17035
- 32: toHaveBeenCalledTimes(n: number): Assertion;
17036
- 33: toBe(expected: unknown): Assertion;
17037
- 34: toEqual(expected: unknown): Assertion;
17038
- 35: toStrictEqual(expected: unknown): Assertion;
17039
- 36: toBeNull(): Assertion;
17040
- 37: toBeDefined(): Assertion;
17041
- 38: toBeGreaterThan(n: number): Assertion;
17042
- 39: toBeLessThanOrEqual(n: number): Assertion;
17043
- 40: toMatch(pattern: RegExp | string): Assertion;
17044
- 41: toThrow(error?: string | Error | RegExp): Assertion;
17045
- 42: toContain(item: unknown): Assertion;
17046
- 43: toContainElement(element: HTMLElement): Assertion;
17047
- 44: toContainHTML(html: string): Assertion;
17048
- 45: toHaveLength(length: number): Assertion;
17049
- 46: rejects: {
17050
- 47: toThrow(error?: string | Error | RegExp): Promise<void>;
17051
- 48: };
17052
- 49: }
17053
- 50: interface ExpectStatic {
17054
- 51: any<T>(classType: new (...args: unknown[]) => T): unknown;
17055
- 52: }
17056
- 53: }
17057
- 54: // Add canvas mocking support
17058
- 55: interface HTMLCanvasElement {
17059
- 56: getContext(contextId: "2d"): CanvasRenderingContext2D | null;
17060
- 57: }
17061
- 58: }
17062
- 59: export {};
17063
- ````
17064
-
17065
17002
## File: src/utils/eslint/dist/index.js
17066
17003
````javascript
17067
17004
1: /* eslint-disable @typescript-eslint/no-require-imports */
@@ -17132,6 +17069,69 @@ tsconfig.json
17132
17069
66: };
17133
17070
````
17134
17071
17072
+ ## File: src/types/testing-library.d.ts
17073
+ ````typescript
17074
+ 1: /// <reference types="jest" />
17075
+ 2: /// <reference types="@testing-library/jest-dom" />
17076
+ 3: // Extend Jest matchers - using module augmentation instead of namespace declaration
17077
+ 4: declare global {
17078
+ 5: namespace jest {
17079
+ 6: interface Matchers<R> {
17080
+ 7: toBeInTheDocument(): R;
17081
+ 8: toHaveTextContent(text: string): R;
17082
+ 9: toBeVisible(): R;
17083
+ 10: toBeDisabled(): R;
17084
+ 11: toBeEnabled(): R;
17085
+ 12: toHaveAttribute(attr: string, value?: string): R;
17086
+ 13: toHaveClass(className: string): R;
17087
+ 14: toHaveStyle(css: React.CSSProperties): R;
17088
+ 15: }
17089
+ 16: }
17090
+ 17: }
17091
+ 18: // Augment Chai assertions for Cypress
17092
+ 19: declare global {
17093
+ 20: namespace Chai {
17094
+ 21: interface Assertion {
17095
+ 22: toBeInTheDocument(): Assertion;
17096
+ 23: toHaveTextContent(text: string): Assertion;
17097
+ 24: toBeVisible(): Assertion;
17098
+ 25: toBeDisabled(): Assertion;
17099
+ 26: toBeEnabled(): Assertion;
17100
+ 27: toHaveAttribute(attr: string, value?: string): Assertion;
17101
+ 28: toHaveClass(...classNames: string[]): Assertion;
17102
+ 29: toHaveStyle(css: React.CSSProperties): Assertion;
17103
+ 30: toHaveBeenCalled(): Assertion;
17104
+ 31: toHaveBeenCalledWith(...args: unknown[]): Assertion;
17105
+ 32: toHaveBeenCalledTimes(n: number): Assertion;
17106
+ 33: toBe(expected: unknown): Assertion;
17107
+ 34: toEqual(expected: unknown): Assertion;
17108
+ 35: toStrictEqual(expected: unknown): Assertion;
17109
+ 36: toBeNull(): Assertion;
17110
+ 37: toBeDefined(): Assertion;
17111
+ 38: toBeGreaterThan(n: number): Assertion;
17112
+ 39: toBeLessThanOrEqual(n: number): Assertion;
17113
+ 40: toMatch(pattern: RegExp | string): Assertion;
17114
+ 41: toThrow(error?: string | Error | RegExp): Assertion;
17115
+ 42: toContain(item: unknown): Assertion;
17116
+ 43: toContainElement(element: HTMLElement): Assertion;
17117
+ 44: toContainHTML(html: string): Assertion;
17118
+ 45: toHaveLength(length: number): Assertion;
17119
+ 46: rejects: {
17120
+ 47: toThrow(error?: string | Error | RegExp): Promise<void>;
17121
+ 48: };
17122
+ 49: }
17123
+ 50: interface ExpectStatic {
17124
+ 51: any<T>(classType: new (...args: unknown[]) => T): unknown;
17125
+ 52: }
17126
+ 53: }
17127
+ 54: // Add canvas mocking support
17128
+ 55: interface HTMLCanvasElement {
17129
+ 56: getContext(contextId: "2d"): CanvasRenderingContext2D | null;
17130
+ 57: }
17131
+ 58: }
17132
+ 59: export {};
17133
+ ````
17134
+
17135
17135
## File: src/__tests__/Index/IndexContent.test.tsx
17136
17136
````typescript
17137
17137
1: import React from "react";
0 commit comments