diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 34d05a0..52ef54a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,6 +34,10 @@ jobs: uses: dart-lang/setup-dart@v1 with: sdk: stable + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 - id: checkout name: Checkout repository uses: actions/checkout@v4 @@ -55,6 +59,24 @@ jobs: run: | dart pub global run coverage:test_with_coverage dart pub global run remove_from_coverage:remove_from_coverage -f coverage/lcov.info -r '\.g\.dart$' + - name: Run a comparison test between qs_dart and qs for JavaScript + continue-on-error: true + working-directory: test/comparison + run: | + set -e + npm install + + # Run the JavaScript and Dart scripts and save their outputs + node_output=$(node qs.js) + dart_output=$(dart run qs.dart) + + # Compare the outputs + if [ "$node_output" == "$dart_output" ]; then + echo "The outputs are identical." + else + echo "The outputs are different." + exit 1 + fi - name: Upload coverage uses: codecov/codecov-action@v4 with: diff --git a/pubspec.yaml b/pubspec.yaml index a40451a..57e68e3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,8 +13,10 @@ dependencies: weak_map: ^3.0.1 dev_dependencies: + cli_script: ^1.0.0 euc: ^1.0.6+8 lints: ^3.0.0 + path: ^1.8.0 test: ^1.25.2 topics: diff --git a/test/comparison/.gitignore b/test/comparison/.gitignore new file mode 100644 index 0000000..d5f19d8 --- /dev/null +++ b/test/comparison/.gitignore @@ -0,0 +1,2 @@ +node_modules +package-lock.json diff --git a/test/comparison/compare_outputs.sh b/test/comparison/compare_outputs.sh new file mode 100755 index 0000000..ebe11b2 --- /dev/null +++ b/test/comparison/compare_outputs.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# Get the directory of the script +script_dir=$(dirname "$0") + +# Run the JavaScript and Dart scripts and save their outputs +node_output=$(node "$script_dir/qs.js") +dart_output=$(dart run "$script_dir/qs.dart") + +# Compare the outputs +if [ "$node_output" == "$dart_output" ]; then + echo "The outputs are identical." + exit 0 +else + echo "The outputs are different." + exit 1 +fi diff --git a/test/comparison/package.json b/test/comparison/package.json new file mode 100644 index 0000000..3da9b28 --- /dev/null +++ b/test/comparison/package.json @@ -0,0 +1,10 @@ +{ + "name": "qs_comparison", + "version": "1.0.0", + "description": "A comparison of query string parsing libraries", + "author": "Klemen Tusar", + "license": "BSD-3-Clause", + "dependencies": { + "qs": "^6.12.1" + } +} diff --git a/test/comparison/qs.dart b/test/comparison/qs.dart new file mode 100644 index 0000000..1e63ec3 --- /dev/null +++ b/test/comparison/qs.dart @@ -0,0 +1,26 @@ +import 'dart:convert' show jsonDecode, jsonEncode; +import 'dart:io' show File, Platform, exitCode, stdout; +import 'package:qs_dart/qs_dart.dart' as qs; +import 'package:cli_script/cli_script.dart' show wrapMain; +import 'package:path/path.dart' as p; + +void main() { + wrapMain(() { + exitCode = 0; + + final String scriptDir = p.dirname(Platform.script.toFilePath()); + final File file = File(p.join(scriptDir, 'test_cases.json')); + final String contents = file.readAsStringSync(); + final List> e2eTestCases = + List>.from( + jsonDecode(contents), + ); + + for (final testCase in e2eTestCases) { + final String encoded = qs.encode(testCase['data']); + final Map decoded = qs.decode(testCase['encoded']); + stdout.writeln('Encoded: $encoded'); + stdout.writeln('Decoded: ${jsonEncode(decoded)}'); + } + }); +} diff --git a/test/comparison/qs.js b/test/comparison/qs.js new file mode 100644 index 0000000..59c2d58 --- /dev/null +++ b/test/comparison/qs.js @@ -0,0 +1,14 @@ +const fs = require('fs'); +const path = require('path'); +const qs = require('qs'); + +// Use path.join to combine __dirname with the relative path to test_cases.json +const filePath = path.join(__dirname, 'test_cases.json'); +const e2eTestCases = JSON.parse(fs.readFileSync(filePath).toString()); + +e2eTestCases.forEach(testCase => { + let encoded = qs.stringify(testCase.data); + let decoded = qs.parse(encoded); + console.log('Encoded: ' + encoded); + console.log('Decoded: ' + JSON.stringify(decoded)); +}); diff --git a/test/comparison/test_cases.json b/test/comparison/test_cases.json new file mode 100644 index 0000000..913a39e --- /dev/null +++ b/test/comparison/test_cases.json @@ -0,0 +1,78 @@ +[ + { + "data": {}, + "encoded": "" + }, + { + "data": { + "a": "b" + }, "encoded": "a=b" + }, + { + "data": { + "a": "b", + "c": "d" + }, + "encoded": "a=b&c=d" + }, + { + "data": { + "a": "b", + "c": "d", + "e": "f" + }, + "encoded": "a=b&c=d&e=f" + }, + { + "data": { + "a": "b", + "c": "d", + "e": [ + "f", + "g", + "h" + ] + }, + "encoded": "a=b&c=d&e[0]=f&e[1]=g&e[2]=h" + }, + { + "data": { + "a": "b", + "c": "d", + "e": [ + "f", + "g", + "h" + ], + "i": { + "j": "k", + "l": "m" + } + }, + "encoded": "a=b&c=d&e[0]=f&e[1]=g&e[2]=h&i[j]=k&i[l]=m" + }, + { + "data": { + "filters": { + "$or": [ + { + "date": { + "$eq": "2020-01-01" + } + }, + { + "date": { + "$eq": "2020-01-02" + } + } + ], + "author": { + "name": { + "$eq": "John Doe" + } + } + } + }, + "encoded": "filters[$or][0][date][$eq]=2020-01-01&filters[$or][1][date][$eq]=2020-01-02&filters[author][name][$eq]=John Doe" + } +]