ftmocks-utils 1.1.7 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +6 -2
  2. package/src/index.js +248 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ftmocks-utils",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
4
  "description": "Util functions for FtMocks",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -16,5 +16,9 @@
16
16
  "bugs": {
17
17
  "url": "https://github.com/SodhanaLibrary/ftmocks-utils/issues"
18
18
  },
19
- "homepage": "https://github.com/SodhanaLibrary/ftmocks-utils#readme"
19
+ "homepage": "https://github.com/SodhanaLibrary/ftmocks-utils#readme",
20
+ "dependencies": {
21
+ "uui": "^1.0.7",
22
+ "uuid": "^11.1.0"
23
+ }
20
24
  }
package/src/index.js CHANGED
@@ -1,7 +1,6 @@
1
- // import fs from 'fs';
2
1
  const fs = require("fs");
3
- // import path from 'path';
4
2
  const path = require("path");
3
+ const { v4: uuidv4 } = require("uuid");
5
4
 
6
5
  const nameToFolder = (name) => {
7
6
  return name.replaceAll(" ", "_");
@@ -636,6 +635,252 @@ function initiateJestEventSnaps(jest, ftmocksConifg, testName) {
636
635
  });
637
636
  }
638
637
 
638
+ const createTest = async (ftmocksConifg, testName) => {
639
+ const testsPath = path.join(getMockDir(ftmocksConifg), "tests.json");
640
+ let tests = [];
641
+ try {
642
+ // Read existing tests
643
+ const testsData = fs.readFileSync(testsPath, "utf8");
644
+ tests = JSON.parse(testsData);
645
+ const etest = tests.find((tst) => tst.name === testName);
646
+ if (!etest) {
647
+ const newTest = {
648
+ id: uuidv4(),
649
+ name: testName,
650
+ };
651
+ tests.push(newTest);
652
+ fs.writeFileSync(testsPath, JSON.stringify(tests, null, 2));
653
+ const folderPath = path.join(
654
+ getMockDir(ftmocksConifg),
655
+ `test_${nameToFolder(testName)}`
656
+ );
657
+ const mockListFilePath = path.join(folderPath, "_mock_list.json");
658
+ fs.mkdir(folderPath, { recursive: true }, (err) => {
659
+ if (err) {
660
+ console.error("Error creating directory:", err);
661
+ } else {
662
+ console.log("Directory created successfully!");
663
+ }
664
+ });
665
+ await fs.appendFile(mockListFilePath, "[]", () => {
666
+ console.log("mock list file created successfully");
667
+ });
668
+
669
+ return newTest;
670
+ } else {
671
+ throw "Test already exists";
672
+ }
673
+ } catch (error) {
674
+ console.error(`Error reading tests.json:`, error);
675
+ return null;
676
+ }
677
+ };
678
+
679
+ const isSameResponse = (req1, req2) => {
680
+ try {
681
+ let matched = true;
682
+ if (req1.response.status !== req2.response.status) {
683
+ matched = false;
684
+ // console.log('not matched at url', req1.method, req2.method);
685
+ } else if (
686
+ (!req1.response.content && req2.response.content) ||
687
+ (req1.response.content && !req2.response.content)
688
+ ) {
689
+ matched = areJsonEqual(
690
+ JSON.parse(req1.response.content) || {},
691
+ JSON.parse(req2.response.content) || {}
692
+ );
693
+ // console.log('not matched at post Data 0', req1.postData, req2.postData);
694
+ } else if (
695
+ req1.response.content &&
696
+ req2.response.content &&
697
+ !areJsonEqual(
698
+ JSON.parse(req1.response.content) || {},
699
+ JSON.parse(req2.response.content) || {}
700
+ )
701
+ ) {
702
+ matched = false;
703
+ }
704
+ // if (matched) {
705
+ // console.log('matched responses', req1, req2);
706
+ // }
707
+ return matched;
708
+ } catch (error) {
709
+ console.error(error);
710
+ return false;
711
+ }
712
+ };
713
+
714
+ const compareMockToMock = (mock1, mock2, matchResponse) => {
715
+ try {
716
+ if (matchResponse) {
717
+ return isSameRequest(mock1, mock2) && isSameResponse(mock1, mock2);
718
+ } else {
719
+ return isSameRequest(mock1, mock2);
720
+ }
721
+ } catch (error) {
722
+ console.error(error);
723
+ return false;
724
+ }
725
+ };
726
+
727
+ const saveIfItIsFile = async (route, testName, ftmocksConifg) => {
728
+ const urlObj = new URL(route.request().url());
729
+
730
+ // Check if URL contains file extension like .js, .png, .css etc
731
+ const fileExtMatch = urlObj.pathname.match(/\.[a-zA-Z0-9]+$/);
732
+ if (fileExtMatch) {
733
+ const fileExt = fileExtMatch[0];
734
+ // Create directory path matching URL structure
735
+ const dirPath = path.join(
736
+ getMockDir(ftmocksConifg),
737
+ `test_${nameToFolder(testName)}`,
738
+ "_files",
739
+ path.dirname(urlObj.pathname)
740
+ );
741
+
742
+ // Create directories if they don't exist
743
+ fs.mkdirSync(dirPath, { recursive: true });
744
+
745
+ // Save file with original name
746
+ const fileName = path.basename(urlObj.pathname);
747
+ const filePath = path.join(dirPath, fileName);
748
+
749
+ const response = await route.fetch();
750
+ const buffer = await response.body();
751
+ fs.writeFileSync(filePath, buffer);
752
+
753
+ await route.continue();
754
+ return true;
755
+ }
756
+ return false;
757
+ };
758
+
759
+ async function recordPlaywrightRoutes(
760
+ page,
761
+ ftmocksConifg,
762
+ config = {
763
+ testName,
764
+ mockPath: "**/*",
765
+ pattern: "^/api/.*",
766
+ avoidDuplicatesInTheTest: true,
767
+ avoidDuplicatesWithDefaultMocks: true,
768
+ }
769
+ ) {
770
+ await page.route(config.mockPath, async (route) => {
771
+ try {
772
+ const urlObj = new URL(route.request().url());
773
+ if (config.pattern && config.pattern.length > 0) {
774
+ const patternRegex = new RegExp(config.pattern);
775
+ if (!patternRegex.test(urlObj.pathname)) {
776
+ await route.continue();
777
+ return;
778
+ }
779
+ }
780
+
781
+ if (await saveIfItIsFile(route, config.testName, ftmocksConifg)) {
782
+ return;
783
+ }
784
+
785
+ const mockData = {
786
+ url: urlObj.pathname + urlObj.search,
787
+ time: new Date().toString(),
788
+ method: route.request().method(),
789
+ request: {
790
+ headers: await route.request().headers(),
791
+ queryString: Array.from(urlObj.searchParams.entries()).map(
792
+ ([name, value]) => ({
793
+ name,
794
+ value,
795
+ })
796
+ ),
797
+ postData: route.request().postData()
798
+ ? {
799
+ mimeType: "application/json",
800
+ text: route.request().postData(),
801
+ }
802
+ : null,
803
+ },
804
+ response: {
805
+ status: (await route.fetch()).status(),
806
+ headers: (await route.fetch()).headers(),
807
+ content: await (await route.fetch()).text(),
808
+ },
809
+ id: crypto.randomUUID(),
810
+ served: false,
811
+ ignoreParams: ftmocksConifg.ignoreParams || [],
812
+ };
813
+
814
+ await createTest(ftmocksConifg, config.testName);
815
+ if (config.avoidDuplicatesInTheTest) {
816
+ // Check if the mock data is a duplicate of a mock data in the test
817
+ const testMockList = loadMockDataFromConfig(
818
+ ftmocksConifg,
819
+ config.testName
820
+ );
821
+ const matchResponse = testMockList.find((mock) =>
822
+ compareMockToMock(mock.fileContent, mockData, true)
823
+ );
824
+ if (matchResponse) {
825
+ console.log("Aborting duplicate mock data in the test");
826
+ await route.continue();
827
+ return;
828
+ }
829
+ }
830
+
831
+ if (config.avoidDuplicatesWithDefaultMocks) {
832
+ // Check if the mock data is a duplicate of a mock data in the test
833
+ const defaultMockList = getDefaultMockDataFromConfig(ftmocksConifg);
834
+ const matchResponse = defaultMockList.find((mock) =>
835
+ compareMockToMock(mock.fileContent, mockData, true)
836
+ );
837
+ if (matchResponse) {
838
+ console.log("Aborting duplicate mock data with default mocks");
839
+ await route.continue();
840
+ return;
841
+ }
842
+ }
843
+
844
+ // Save the mock data to the test
845
+ const mockListPath = path.join(
846
+ getMockDir(ftmocksConifg),
847
+ `test_${nameToFolder(config.testName)}`,
848
+ "_mock_list.json"
849
+ );
850
+ let mockList = [];
851
+ if (fs.existsSync(mockListPath)) {
852
+ mockList = JSON.parse(fs.readFileSync(mockListPath, "utf8"));
853
+ }
854
+ mockList.push({
855
+ id: mockData.id,
856
+ url: mockData.url,
857
+ method: mockData.method,
858
+ time: mockData.time,
859
+ });
860
+
861
+ // Create test directory if it doesn't exist
862
+ const testDir = path.join(
863
+ getMockDir(ftmocksConifg),
864
+ `test_${nameToFolder(config.testName)}`
865
+ );
866
+ if (!fs.existsSync(testDir)) {
867
+ fs.mkdirSync(testDir, { recursive: true });
868
+ }
869
+ fs.writeFileSync(mockListPath, JSON.stringify(mockList, null, 2));
870
+ const mocDataPath = path.join(
871
+ getMockDir(ftmocksConifg),
872
+ `test_${nameToFolder(config.testName)}`,
873
+ `mock_${mockData.id}.json`
874
+ );
875
+ fs.writeFileSync(mocDataPath, JSON.stringify(mockData, null, 2));
876
+ await route.continue();
877
+ } catch (error) {
878
+ console.error(error);
879
+ await route.continue();
880
+ }
881
+ });
882
+ }
883
+
639
884
  // Export functions as a module
640
885
  module.exports = {
641
886
  compareMockToRequest,
@@ -654,4 +899,5 @@ module.exports = {
654
899
  initiateConsoleLogs,
655
900
  initiatePlaywrightRoutes,
656
901
  initiateJestEventSnaps,
902
+ recordPlaywrightRoutes,
657
903
  };