|
43 | 43 |
|
44 | 44 | # A test double to mock the Gzip compression and keep the 'fake-compressed' result readable in test failures
|
45 | 45 | class GzipWriterDouble < StringIO
|
| 46 | + GZIP_PREFIX = '$GZIP$:'.freeze |
46 | 47 | def close
|
47 | 48 | super
|
48 |
| - self # `GzipWriter#close` returns `self` after closing (allowing method chaining), unlike default `StringIO#close` |
| 49 | + # `GzipWriter#close` returns `self` after closing (allowing use to use method chaining), unlike `StringIO#close` |
| 50 | + self |
49 | 51 | end
|
50 | 52 |
|
51 | 53 | def string
|
52 |
| - "GZIP<#{super}>" |
| 54 | + "#{GZIP_PREFIX}#{super}" |
53 | 55 | end
|
54 | 56 | end
|
55 | 57 |
|
56 | 58 | describe Fastlane::Actions::IosSendAppSizeMetricsAction do
|
57 | 59 | let(:test_data_dir) { File.join(File.dirname(__FILE__), 'test-data', 'app_size_metrics') }
|
| 60 | + let(:mocked_endpoint) { 'https://localhost/api/metrics' } |
| 61 | + let(:mocked_token) { 'token/1' } |
| 62 | + |
| 63 | + # Utility method to turn a minified JSON into a pretty-formatted JSON (without the GZIP fake prefix if any) |
| 64 | + # To make any test failure and diff easier to debug |
| 65 | + def pretty_json(json_string) |
| 66 | + JSON.pretty_generate(JSON.parse(json_string.delete_prefix(GzipWriterDouble::GZIP_PREFIX))) |
| 67 | + end |
58 | 68 |
|
59 | 69 | def test_app_size_action(fake_ipa_size:, expected_json:, **other_action_args)
|
60 |
| - mocked_endpoint = 'https://localhost/api/metrics' |
61 | 70 | in_tmp_dir do |tmp_dir|
|
| 71 | + # Arrange: Generate a fake `.ipa` file with the expected size |
62 | 72 | ipa_path = File.join(tmp_dir, 'fake.ipa')
|
63 | 73 | File.write(ipa_path, SecureRandom.random_bytes(fake_ipa_size))
|
| 74 | + |
| 75 | + # Arrange: Mock GzipWriter with a mock for easier debugging in case of test failures |
64 | 76 | allow(Zlib::GzipWriter).to receive(:new).and_return(GzipWriterDouble.new)
|
65 | 77 |
|
| 78 | + # Arrange: Stub any request to the mocked_endpoint, and memorize the received body |
66 | 79 | expected_headers = {
|
67 |
| - Authorization: 'Bearer token/1', |
| 80 | + Authorization: "Bearer #{mocked_token}", |
68 | 81 | 'Content-Type': 'application/json',
|
69 | 82 | 'Content-Encoding': 'gzip'
|
70 | 83 | }
|
| 84 | + last_received_body = nil |
| 85 | + stub = stub_request(:post, mocked_endpoint).with(headers: expected_headers) do |req| |
| 86 | + last_received_body = req.body |
| 87 | + end.to_return(status: 200) |
71 | 88 |
|
72 |
| - stub = stub_request(:post, mocked_endpoint).with( |
73 |
| - headers: expected_headers, |
74 |
| - body: "GZIP<#{expected_json}>" |
75 |
| - ).to_return(status: 200) |
76 |
| - |
| 89 | + # Act |
77 | 90 | code = run_described_fastlane_action(
|
78 | 91 | api_base_url: mocked_endpoint,
|
79 |
| - api_token: 'token/1', |
| 92 | + api_token: mocked_token, |
80 | 93 | ipa_path: ipa_path,
|
81 | 94 | **other_action_args
|
82 | 95 | )
|
83 | 96 |
|
| 97 | + # Asserts |
84 | 98 | expect(stub).to have_been_made.once
|
85 | 99 | expect(code).to eq(200)
|
| 100 | + expect(last_received_body).to start_with(GzipWriterDouble::GZIP_PREFIX), 'Payload is expected to be GZipped, but was not' |
| 101 | + # Compare the payloads as pretty-formatted JSON, to make the diff in test failures more readable if one happen |
| 102 | + expect(pretty_json(last_received_body)).to eq(pretty_json(expected_json)), 'Decompressed JSON payload was not as expected' |
| 103 | + # Compare the payloads as raw strings as a final check |
| 104 | + expect(last_received_body).to eq(GzipWriterDouble.new(expected_json).string) |
86 | 105 | end
|
87 | 106 | end
|
88 | 107 |
|
|
0 commit comments