1 | <?php |
||
23 | class PassFactoryTest extends TestCase |
||
24 | { |
||
25 | /** |
||
26 | * @var PassFactory |
||
27 | */ |
||
28 | protected $factory; |
||
29 | |||
30 | /** |
||
31 | * @var boolean |
||
32 | */ |
||
33 | private $skipPackageTest = false; |
||
34 | |||
35 | /** |
||
36 | * @inheritDoc |
||
37 | */ |
||
38 | protected function setUp(): void |
||
39 | { |
||
40 | // The PassFactory defaults can be overwritten by setting environment |
||
41 | // variables or through phpunit configuration when testing. |
||
42 | |||
43 | $p12File = getenv('P12_CERT_PATH') ?: __DIR__ . '/../../cert/pass.com.example.testpass.p12'; |
||
44 | $p12Pass = getenv('P12_CERT_PASS') ?: '123456'; |
||
45 | $wwdrFile = getenv('WWDR_CERT_PATH') ?: __DIR__ . '/../../cert/wwdr.pem'; |
||
46 | $passTypeIdentifier = getenv('PASS_TYPE_ID') ?: 'pass-type-identifier'; |
||
47 | $teamIdentifier = getenv('TEAM_ID') ?: 'team-identifier'; |
||
48 | $orgName = getenv('ORG_NAME') ?: 'organization-name'; |
||
49 | |||
50 | $this->factory = new PassFactory($passTypeIdentifier, $teamIdentifier, $orgName, $p12File, $p12Pass, $wwdrFile); |
||
51 | } |
||
52 | |||
53 | /** |
||
54 | * Factory methods |
||
55 | */ |
||
56 | public function testFactoryMethods() |
||
57 | { |
||
58 | $this->factory->setOverwrite(true); |
||
59 | $this->assertTrue($this->factory->isOverwrite()); |
||
60 | |||
61 | $this->factory->setOutputPath('/tmp'); |
||
62 | $this->assertEquals($this->factory->getOutputPath(), '/tmp'); |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * Factory package |
||
67 | * @throws Exception |
||
68 | */ |
||
69 | public function testFactoryPackage() |
||
70 | { |
||
71 | // Create an event ticket |
||
72 | $pass = new EventTicket(time(), 'The Beat Goes On'); |
||
73 | $pass->setBackgroundColor('rgb(60, 65, 76)'); |
||
74 | $pass->setLogoText('Apple Inc.'); |
||
75 | |||
76 | // Create pass structure |
||
77 | $structure = new Structure(); |
||
78 | |||
79 | // Add primary field |
||
80 | $primary = new Field('event', 'The Beat Goes On'); |
||
81 | $primary->setLabel('Event'); |
||
82 | $structure->addPrimaryField($primary); |
||
83 | |||
84 | // Add secondary field |
||
85 | $secondary = new Field('location', 'Moscone West'); |
||
86 | $secondary->setLabel('Location'); |
||
87 | $structure->addSecondaryField($secondary); |
||
88 | |||
89 | // Add auxiliary field |
||
90 | $auxiliary = new Field('datetime', '2013-04-15 @10:25'); |
||
91 | $auxiliary->setLabel('Date & Time'); |
||
92 | $structure->addAuxiliaryField($auxiliary); |
||
93 | |||
94 | $auxiliary = new Pass\NumberField('price', '12.34'); |
||
95 | $auxiliary->setLabel('Price'); |
||
96 | $auxiliary->setCurrencyCode('USD'); |
||
97 | $structure->addAuxiliaryField($auxiliary); |
||
98 | |||
99 | // Add icon image |
||
100 | $icon = new Image(__DIR__ . '/../../img/icon.png', 'icon'); |
||
101 | $pass->addImage($icon); |
||
102 | |||
103 | // Set pass structure |
||
104 | $pass->setStructure($structure); |
||
105 | |||
106 | // Add barcode |
||
107 | $barcode = new Barcode(Barcode::TYPE_QR, 'barcodeMessage'); |
||
108 | $pass->setBarcode($barcode); |
||
109 | |||
110 | // Add Localizations (this also tests zipping subdirectories) |
||
111 | $englishText = array( |
||
112 | 'created_by' => 'Pass produced by php-passbook' |
||
113 | ); |
||
114 | |||
115 | $spanishText = array( |
||
116 | 'created_by' => 'Pase producido por php-passbook' |
||
117 | ); |
||
118 | |||
119 | $es = new Localization('es'); |
||
120 | $es->addStrings($spanishText); |
||
121 | $pass->addLocalization($es); |
||
122 | |||
123 | $en = new Localization('en'); |
||
124 | $en->addStrings($englishText); |
||
125 | $pass->addLocalization($en); |
||
126 | |||
127 | $field = new Field('exclusive_card', 'created_by'); |
||
128 | $structure->addBackField($field); |
||
129 | |||
130 | if ($this->skipPackageTest) { |
||
131 | $this->markTestIncomplete( |
||
132 | 'P12 and/or WWDR certificate(s) not found' |
||
133 | ); |
||
134 | } |
||
135 | |||
136 | $this->factory->setOutputPath(__DIR__ . '/../../../www/passes'); |
||
137 | $file = $this->factory->package($pass); |
||
138 | $this->assertInstanceOf('SplFileObject', $file); |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * @throws InvalidArgumentException|Exception |
||
143 | */ |
||
144 | public function testPackagePassWithoutSerialNumberThrowsException() |
||
145 | { |
||
146 | $this->expectException(InvalidArgumentException::class); |
||
147 | $pass = new Pass('', 'pass without a serial number'); |
||
148 | |||
149 | $this->factory->setOutputPath('/tmp'); |
||
150 | $this->factory->package($pass); |
||
151 | } |
||
152 | |||
153 | /** |
||
154 | * @throws Exception |
||
155 | */ |
||
156 | public function testRequiredInformationInPassNotOverwrittenByFactory() |
||
157 | { |
||
158 | $passOrganizationName = 'organization name in pass'; |
||
159 | $passTeamIdentifier = 'team identifier in pass'; |
||
160 | $passPassTypeIdentifier = 'pass type identifier in pass'; |
||
161 | |||
162 | $pass = new Pass('serial_number', 'description'); |
||
163 | $pass->setOrganizationName($passOrganizationName); |
||
164 | $pass->setTeamIdentifier($passTeamIdentifier); |
||
165 | $pass->setPassTypeIdentifier($passPassTypeIdentifier); |
||
166 | |||
167 | // Icon is required |
||
168 | $icon = new Image(__DIR__ . '/../../img/icon.png', 'icon'); |
||
169 | $pass->addImage($icon); |
||
170 | |||
171 | $this->factory->setOutputPath('/tmp'); |
||
172 | $this->factory->setOverwrite(true); |
||
173 | $this->factory->setSkipSignature(true); |
||
174 | $this->factory->package($pass); |
||
175 | |||
176 | self::assertEquals($passOrganizationName, $pass->getOrganizationName()); |
||
177 | self::assertEquals($passTeamIdentifier, $pass->getTeamIdentifier()); |
||
178 | self::assertEquals($passPassTypeIdentifier, $pass->getPassTypeIdentifier()); |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * |
||
183 | */ |
||
184 | public function testNormalizedOutputPath() |
||
185 | { |
||
186 | $s = DIRECTORY_SEPARATOR; |
||
187 | |||
188 | $this->factory->setOutputPath("path-ending-with-separator{$s}"); |
||
189 | self::assertEquals("path-ending-with-separator{$s}", $this->factory->getNormalizedOutputPath()); |
||
190 | |||
191 | $this->factory->setOutputPath("path-not-ending-with-separator"); |
||
192 | self::assertEquals("path-not-ending-with-separator{$s}", $this->factory->getNormalizedOutputPath()); |
||
193 | |||
194 | $this->factory->setOutputPath("path-ending-with-multiple-separators{$s}{$s}"); |
||
195 | self::assertEquals("path-ending-with-multiple-separators{$s}", $this->factory->getNormalizedOutputPath()); |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * @throws PassInvalidException|Exception |
||
200 | */ |
||
201 | public function testPassThatFailsValidationThrowsException() |
||
202 | { |
||
203 | $this->expectException(PassInvalidException::class); |
||
204 | $this->factory->setPassValidator(new PassValidator()); |
||
205 | |||
206 | $invalidPass = new Pass('serial number', 'description'); |
||
207 | $this->factory->package($invalidPass); |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * @throws Exception |
||
212 | */ |
||
213 | public function testSpecifyPassName() |
||
214 | { |
||
215 | // Make sure the file doesn't already exist as that would invalidate the test. |
||
216 | if (file_exists('/tmp/passname.pkpass')) { |
||
217 | unlink('/tmp/passname.pkpass'); |
||
218 | } |
||
219 | |||
220 | $pass = new Pass('serial number', 'description'); |
||
221 | |||
222 | // Icon is required |
||
223 | $icon = new Image(__DIR__ . '/../../img/icon.png', 'icon'); |
||
224 | $pass->addImage($icon); |
||
225 | |||
226 | $this->factory->setOutputPath('/tmp'); |
||
227 | $this->factory->setSkipSignature(true); |
||
228 | $this->factory->package($pass, 'pass name'); |
||
229 | |||
230 | self::assertTrue(file_exists('/tmp/passname.pkpass')); |
||
231 | } |
||
232 | } |
||
233 |